@burdenoff/microfe-organization 2026.527.3 → 2026.527.5
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.
- package/dist/generated/global-types.js +3 -1
- package/dist/generated/global-types.js.map +1 -1
- package/dist/organization-management/UserOrganizationRoot.js +39 -28
- package/dist/organization-management/UserOrganizationRoot.js.map +1 -1
- package/dist/organization-management/UserOrganizationRoutes.js +12 -8
- package/dist/organization-management/UserOrganizationRoutes.js.map +1 -1
- package/dist/organization-management/modules/members/components/BulkInviteForm.js +291 -0
- package/dist/organization-management/modules/members/components/BulkInviteForm.js.map +1 -0
- package/dist/organization-management/modules/members/pages/InviteMemberPage.js +65 -42
- package/dist/organization-management/modules/members/pages/InviteMemberPage.js.map +1 -1
- package/dist/organization-management/modules/members/pages/InvitePeoplePage.js +95 -0
- package/dist/organization-management/modules/members/pages/InvitePeoplePage.js.map +1 -0
- package/dist/organization-management/modules/members/utils/bulkInviteCsv.js +52 -0
- package/dist/organization-management/modules/members/utils/bulkInviteCsv.js.map +1 -0
- package/dist/organization-management/modules/organizations/pages/OrganizationDetailPage.js +163 -151
- package/dist/organization-management/modules/organizations/pages/OrganizationDetailPage.js.map +1 -1
- package/dist/organization-management/modules/workspaces/components/AddWorkspaceMemberDialog.js +16 -0
- package/dist/organization-management/modules/workspaces/components/AddWorkspaceMemberDialog.js.map +1 -1
- package/dist/organization-management/modules/workspaces/components/WorkspaceForm.js +7 -7
- package/package.json +1 -1
|
@@ -10,12 +10,12 @@ import { useOrganizationPageView as c } from "../../../hooks/useOrganizationPage
|
|
|
10
10
|
import { useWorkspacesByOrganization as l } from "../../workspaces/hooks/useWorkspaces.js";
|
|
11
11
|
import { WorkspaceCard as u } from "../../workspaces/components/WorkspaceCard.js";
|
|
12
12
|
import { useMemo as d, useState as f } from "react";
|
|
13
|
-
import { ArrowLeft as p, Briefcase as m, Building as h, Edit as g,
|
|
14
|
-
import { usePermissions as
|
|
15
|
-
import { jsx as
|
|
16
|
-
import { useParams as
|
|
13
|
+
import { ArrowLeft as p, Briefcase as m, Building as h, Edit as g, UserPlus as _, Users as v } from "lucide-react";
|
|
14
|
+
import { usePermissions as y } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
15
|
+
import { jsx as b, jsxs as x } from "react/jsx-runtime";
|
|
16
|
+
import { useParams as S } from "react-router-dom";
|
|
17
17
|
//#region src/organization-management/modules/organizations/pages/OrganizationDetailPage.tsx
|
|
18
|
-
function
|
|
18
|
+
function C(e) {
|
|
19
19
|
return new Date(e).toLocaleDateString("en-US", {
|
|
20
20
|
year: "numeric",
|
|
21
21
|
month: "long",
|
|
@@ -24,272 +24,284 @@ function S(e) {
|
|
|
24
24
|
minute: "2-digit"
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
|
-
function
|
|
28
|
-
let
|
|
29
|
-
c("organizations.detail", { organizationId:
|
|
30
|
-
let { navigate:
|
|
27
|
+
function w() {
|
|
28
|
+
let w = r(), { id: T } = S();
|
|
29
|
+
c("organizations.detail", { organizationId: T });
|
|
30
|
+
let { navigate: E, basePath: D = "/organizations" } = e(), { hasPermission: O, isLoading: k } = y(), { organization: A, loading: j, error: M } = t(T ?? ""), [N, P] = f("overview"), { workspaces: F, loading: I, error: L, refetch: R } = l(N === "workspaces" && T ? T ?? "" : "", 50, 0), z = d(() => [{
|
|
31
31
|
id: "overview",
|
|
32
|
-
label:
|
|
32
|
+
label: w("organizations.detail.tab.overview", "Overview")
|
|
33
33
|
}, {
|
|
34
34
|
id: "workspaces",
|
|
35
|
-
label: `${
|
|
35
|
+
label: `${w("organizations.detail.tab.workspaces", "Workspaces")} (${N === "workspaces" ? F.length : A?.workspaceCount ?? 0})`
|
|
36
36
|
}], [
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
N,
|
|
38
|
+
A?.workspaceCount,
|
|
39
|
+
w,
|
|
40
|
+
F.length
|
|
41
41
|
]);
|
|
42
|
-
return
|
|
42
|
+
return k ? /* @__PURE__ */ b("div", {
|
|
43
43
|
className: "min-h-full bg-[var(--color-bg-canvas)] p-6",
|
|
44
|
-
children: /* @__PURE__ */
|
|
45
|
-
}) :
|
|
44
|
+
children: /* @__PURE__ */ b(i, { message: w("common.loadingPermissions", "Loading permissions...") })
|
|
45
|
+
}) : O(s.ORG_READ) ? j ? /* @__PURE__ */ b("div", {
|
|
46
46
|
className: "min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6",
|
|
47
|
-
children: /* @__PURE__ */
|
|
48
|
-
}) :
|
|
47
|
+
children: /* @__PURE__ */ b(i, { message: w("organizations.detail.loading", "Loading organization details...") })
|
|
48
|
+
}) : M || !A ? /* @__PURE__ */ b("div", {
|
|
49
49
|
className: "min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6",
|
|
50
|
-
children: /* @__PURE__ */
|
|
51
|
-
message:
|
|
50
|
+
children: /* @__PURE__ */ b(a, {
|
|
51
|
+
message: M?.message || w("organizations.detail.notFound", "Organization not found"),
|
|
52
52
|
action: {
|
|
53
|
-
label:
|
|
54
|
-
onClick: () =>
|
|
53
|
+
label: w("organizations.create.back", "Back to Organizations"),
|
|
54
|
+
onClick: () => E(D)
|
|
55
55
|
}
|
|
56
56
|
})
|
|
57
|
-
}) : /* @__PURE__ */
|
|
57
|
+
}) : /* @__PURE__ */ b("div", {
|
|
58
58
|
className: "min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6 animate-in fade-in duration-300",
|
|
59
|
-
children: /* @__PURE__ */
|
|
59
|
+
children: /* @__PURE__ */ x("div", {
|
|
60
60
|
className: "mx-auto flex w-full max-w-7xl flex-col gap-6",
|
|
61
|
-
children: [/* @__PURE__ */
|
|
61
|
+
children: [/* @__PURE__ */ x("div", {
|
|
62
62
|
className: "space-y-4",
|
|
63
|
-
children: [/* @__PURE__ */
|
|
63
|
+
children: [/* @__PURE__ */ x("button", {
|
|
64
64
|
type: "button",
|
|
65
|
-
onClick: () =>
|
|
65
|
+
onClick: () => E(D),
|
|
66
66
|
className: "inline-flex min-h-10 items-center gap-2 text-[var(--color-text-secondary)] transition-all duration-200 hover:text-[var(--color-text-primary)] active:scale-[0.98]",
|
|
67
|
-
children: [/* @__PURE__ */
|
|
67
|
+
children: [/* @__PURE__ */ b(p, {
|
|
68
68
|
size: 20,
|
|
69
69
|
"aria-hidden": "true"
|
|
70
|
-
}), /* @__PURE__ */
|
|
70
|
+
}), /* @__PURE__ */ b("span", {
|
|
71
71
|
className: "text-sm font-medium",
|
|
72
|
-
children:
|
|
72
|
+
children: w("organizations.create.back", "Back to Organizations")
|
|
73
73
|
})]
|
|
74
|
-
}), /* @__PURE__ */
|
|
74
|
+
}), /* @__PURE__ */ x("div", {
|
|
75
75
|
className: "flex flex-col gap-4 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] p-5 shadow-[var(--shadow-elevation-1)] lg:flex-row lg:items-start lg:justify-between",
|
|
76
|
-
children: [/* @__PURE__ */
|
|
76
|
+
children: [/* @__PURE__ */ x("div", {
|
|
77
77
|
className: "flex min-w-0 items-start gap-4",
|
|
78
|
-
children: [/* @__PURE__ */
|
|
78
|
+
children: [/* @__PURE__ */ b("div", {
|
|
79
79
|
className: "flex size-16 items-center justify-center rounded-xl bg-[var(--color-status-info-bgSubtle)] text-[var(--color-status-info-text)]",
|
|
80
|
-
children: /* @__PURE__ */
|
|
80
|
+
children: /* @__PURE__ */ b(h, {
|
|
81
81
|
size: 28,
|
|
82
82
|
"aria-hidden": "true"
|
|
83
83
|
})
|
|
84
|
-
}), /* @__PURE__ */
|
|
84
|
+
}), /* @__PURE__ */ x("div", {
|
|
85
85
|
className: "min-w-0 space-y-2",
|
|
86
86
|
children: [
|
|
87
|
-
/* @__PURE__ */
|
|
87
|
+
/* @__PURE__ */ x("div", {
|
|
88
88
|
className: "flex flex-wrap items-start gap-3",
|
|
89
|
-
children: [/* @__PURE__ */
|
|
89
|
+
children: [/* @__PURE__ */ b("h1", {
|
|
90
90
|
className: "text-3xl font-bold text-[var(--color-text-primary)]",
|
|
91
|
-
children:
|
|
92
|
-
}), /* @__PURE__ */
|
|
91
|
+
children: A.name
|
|
92
|
+
}), /* @__PURE__ */ b(n, { status: A.status })]
|
|
93
93
|
}),
|
|
94
|
-
/* @__PURE__ */
|
|
94
|
+
/* @__PURE__ */ x("p", {
|
|
95
95
|
className: "break-all font-mono text-sm text-[var(--color-text-secondary)]",
|
|
96
|
-
children: ["/",
|
|
96
|
+
children: ["/", A.slug]
|
|
97
97
|
}),
|
|
98
|
-
|
|
98
|
+
A.description ? /* @__PURE__ */ b("p", {
|
|
99
99
|
className: "max-w-2xl text-sm text-[var(--color-text-secondary)]",
|
|
100
|
-
children:
|
|
100
|
+
children: A.description
|
|
101
101
|
}) : null
|
|
102
102
|
]
|
|
103
103
|
})]
|
|
104
|
-
}), /* @__PURE__ */
|
|
104
|
+
}), /* @__PURE__ */ x("div", {
|
|
105
105
|
className: "flex flex-col gap-3 sm:flex-row",
|
|
106
|
-
children: [
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
106
|
+
children: [
|
|
107
|
+
O(s.MEMBER_LIST) && /* @__PURE__ */ x("button", {
|
|
108
|
+
type: "button",
|
|
109
|
+
onClick: () => E(`${D}/${T}/members`),
|
|
110
|
+
className: "inline-flex min-h-11 items-center justify-center gap-2 rounded-lg border border-[var(--color-border-default)] px-4 py-2.5 text-[var(--color-text-primary)] transition-all duration-200 hover:bg-[var(--color-bg-subtle)]",
|
|
111
|
+
children: [/* @__PURE__ */ b(v, {
|
|
112
|
+
size: 16,
|
|
113
|
+
"aria-hidden": "true"
|
|
114
|
+
}), /* @__PURE__ */ b("span", { children: O(s.MEMBER_INVITE) ? w("organizations.detail.manageMembers", "Manage Members") : w("organizations.detail.viewMembers", "View Members") })]
|
|
115
|
+
}),
|
|
116
|
+
O(s.MEMBER_INVITE) && /* @__PURE__ */ x("button", {
|
|
117
|
+
type: "button",
|
|
118
|
+
onClick: () => E(`${D}/${T}/members/invite`),
|
|
119
|
+
className: "inline-flex min-h-11 items-center justify-center gap-2 rounded-lg border border-[var(--color-border-default)] px-4 py-2.5 text-[var(--color-text-primary)] transition-all duration-200 hover:bg-[var(--color-bg-subtle)]",
|
|
120
|
+
children: [/* @__PURE__ */ b(_, {
|
|
121
|
+
size: 16,
|
|
122
|
+
"aria-hidden": "true"
|
|
123
|
+
}), /* @__PURE__ */ b("span", { children: w("members.invite.button", "Invite Member") })]
|
|
124
|
+
}),
|
|
125
|
+
O(s.ORG_UPDATE) && /* @__PURE__ */ x("button", {
|
|
126
|
+
type: "button",
|
|
127
|
+
onClick: () => E(`${D}/${T}/edit`),
|
|
128
|
+
className: "inline-flex min-h-11 items-center justify-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-4 py-2.5 text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90 active:scale-[0.98]",
|
|
129
|
+
children: [/* @__PURE__ */ b(g, {
|
|
130
|
+
size: 16,
|
|
131
|
+
"aria-hidden": "true"
|
|
132
|
+
}), /* @__PURE__ */ b("span", { children: w("organizations.edit.title", "Edit Organization") })]
|
|
133
|
+
})
|
|
134
|
+
]
|
|
123
135
|
})]
|
|
124
136
|
})]
|
|
125
|
-
}), /* @__PURE__ */
|
|
137
|
+
}), /* @__PURE__ */ x("div", {
|
|
126
138
|
className: "rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] shadow-[var(--shadow-elevation-1)]",
|
|
127
|
-
children: [/* @__PURE__ */
|
|
139
|
+
children: [/* @__PURE__ */ b("div", {
|
|
128
140
|
className: "overflow-x-auto border-b border-[var(--color-border-default)]",
|
|
129
|
-
children: /* @__PURE__ */
|
|
141
|
+
children: /* @__PURE__ */ b("div", {
|
|
130
142
|
className: "flex min-w-max gap-2 px-4 pt-4 sm:px-6",
|
|
131
|
-
children:
|
|
132
|
-
let t =
|
|
133
|
-
return /* @__PURE__ */
|
|
143
|
+
children: z.map((e) => {
|
|
144
|
+
let t = N === e.id;
|
|
145
|
+
return /* @__PURE__ */ b("button", {
|
|
134
146
|
type: "button",
|
|
135
|
-
onClick: () =>
|
|
147
|
+
onClick: () => P(e.id),
|
|
136
148
|
className: `inline-flex min-h-11 items-center rounded-t-lg border-b-2 px-4 py-3 text-sm font-medium transition-colors ${t ? "border-[var(--color-action-primary-bg)] text-[var(--color-action-primary-bg)]" : "border-transparent text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)]"}`,
|
|
137
149
|
"aria-pressed": t,
|
|
138
150
|
children: e.label
|
|
139
151
|
}, e.id);
|
|
140
152
|
})
|
|
141
153
|
})
|
|
142
|
-
}), /* @__PURE__ */
|
|
154
|
+
}), /* @__PURE__ */ b("div", {
|
|
143
155
|
className: "p-4 sm:p-6",
|
|
144
|
-
children:
|
|
156
|
+
children: N === "overview" ? /* @__PURE__ */ x("div", {
|
|
145
157
|
className: "grid grid-cols-1 gap-6 xl:grid-cols-[minmax(0,1fr)_320px]",
|
|
146
|
-
children: [/* @__PURE__ */
|
|
158
|
+
children: [/* @__PURE__ */ x("section", {
|
|
147
159
|
className: "rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-canvas)] p-5",
|
|
148
|
-
children: [/* @__PURE__ */
|
|
160
|
+
children: [/* @__PURE__ */ b("h2", {
|
|
149
161
|
className: "text-lg font-semibold text-[var(--color-text-primary)]",
|
|
150
|
-
children:
|
|
151
|
-
}), /* @__PURE__ */
|
|
162
|
+
children: w("organizations.detail.detailsSection", "Organization details")
|
|
163
|
+
}), /* @__PURE__ */ x("dl", {
|
|
152
164
|
className: "mt-5 grid grid-cols-1 gap-4 sm:grid-cols-2",
|
|
153
165
|
children: [
|
|
154
|
-
/* @__PURE__ */
|
|
166
|
+
/* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("dt", {
|
|
155
167
|
className: "text-sm font-medium text-[var(--color-text-secondary)]",
|
|
156
|
-
children:
|
|
157
|
-
}), /* @__PURE__ */
|
|
168
|
+
children: w("common.name", "Name")
|
|
169
|
+
}), /* @__PURE__ */ b("dd", {
|
|
158
170
|
className: "mt-1 text-sm text-[var(--color-text-primary)]",
|
|
159
|
-
children:
|
|
171
|
+
children: A.name
|
|
160
172
|
})] }),
|
|
161
|
-
/* @__PURE__ */
|
|
173
|
+
/* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("dt", {
|
|
162
174
|
className: "text-sm font-medium text-[var(--color-text-secondary)]",
|
|
163
|
-
children:
|
|
164
|
-
}), /* @__PURE__ */
|
|
175
|
+
children: w("common.slug", "Slug")
|
|
176
|
+
}), /* @__PURE__ */ b("dd", {
|
|
165
177
|
className: "mt-1 break-all font-mono text-sm text-[var(--color-text-primary)]",
|
|
166
|
-
children:
|
|
178
|
+
children: A.slug
|
|
167
179
|
})] }),
|
|
168
|
-
/* @__PURE__ */
|
|
180
|
+
/* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("dt", {
|
|
169
181
|
className: "text-sm font-medium text-[var(--color-text-secondary)]",
|
|
170
|
-
children:
|
|
171
|
-
}), /* @__PURE__ */
|
|
182
|
+
children: w("common.status", "Status")
|
|
183
|
+
}), /* @__PURE__ */ b("dd", {
|
|
172
184
|
className: "mt-1",
|
|
173
|
-
children: /* @__PURE__ */
|
|
185
|
+
children: /* @__PURE__ */ b(n, { status: A.status })
|
|
174
186
|
})] }),
|
|
175
|
-
/* @__PURE__ */
|
|
187
|
+
/* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("dt", {
|
|
176
188
|
className: "text-sm font-medium text-[var(--color-text-secondary)]",
|
|
177
|
-
children:
|
|
178
|
-
}), /* @__PURE__ */
|
|
189
|
+
children: w("organizations.detail.workspaceCount", "Workspace count")
|
|
190
|
+
}), /* @__PURE__ */ b("dd", {
|
|
179
191
|
className: "mt-1 text-sm text-[var(--color-text-primary)]",
|
|
180
|
-
children:
|
|
192
|
+
children: A.workspaceCount ?? 0
|
|
181
193
|
})] }),
|
|
182
|
-
|
|
194
|
+
A.website ? /* @__PURE__ */ x("div", {
|
|
183
195
|
className: "sm:col-span-2",
|
|
184
|
-
children: [/* @__PURE__ */
|
|
196
|
+
children: [/* @__PURE__ */ b("dt", {
|
|
185
197
|
className: "text-sm font-medium text-[var(--color-text-secondary)]",
|
|
186
|
-
children:
|
|
187
|
-
}), /* @__PURE__ */
|
|
198
|
+
children: w("organizations.detail.website", "Website")
|
|
199
|
+
}), /* @__PURE__ */ b("dd", {
|
|
188
200
|
className: "mt-1 break-all text-sm",
|
|
189
|
-
children: /* @__PURE__ */
|
|
190
|
-
href:
|
|
201
|
+
children: /* @__PURE__ */ b("a", {
|
|
202
|
+
href: A.website,
|
|
191
203
|
target: "_blank",
|
|
192
204
|
rel: "noreferrer",
|
|
193
205
|
className: "text-[var(--color-action-primary-bg)] underline-offset-2 hover:underline",
|
|
194
|
-
children:
|
|
206
|
+
children: A.website
|
|
195
207
|
})
|
|
196
208
|
})]
|
|
197
209
|
}) : null,
|
|
198
|
-
|
|
210
|
+
A.description ? /* @__PURE__ */ x("div", {
|
|
199
211
|
className: "sm:col-span-2",
|
|
200
|
-
children: [/* @__PURE__ */
|
|
212
|
+
children: [/* @__PURE__ */ b("dt", {
|
|
201
213
|
className: "text-sm font-medium text-[var(--color-text-secondary)]",
|
|
202
|
-
children:
|
|
203
|
-
}), /* @__PURE__ */
|
|
214
|
+
children: w("common.description", "Description")
|
|
215
|
+
}), /* @__PURE__ */ b("dd", {
|
|
204
216
|
className: "mt-1 text-sm leading-6 text-[var(--color-text-primary)]",
|
|
205
|
-
children:
|
|
217
|
+
children: A.description
|
|
206
218
|
})]
|
|
207
219
|
}) : null
|
|
208
220
|
]
|
|
209
221
|
})]
|
|
210
|
-
}), /* @__PURE__ */
|
|
222
|
+
}), /* @__PURE__ */ x("aside", {
|
|
211
223
|
className: "rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-canvas)] p-5",
|
|
212
|
-
children: [/* @__PURE__ */
|
|
224
|
+
children: [/* @__PURE__ */ b("h2", {
|
|
213
225
|
className: "text-lg font-semibold text-[var(--color-text-primary)]",
|
|
214
|
-
children:
|
|
215
|
-
}), /* @__PURE__ */
|
|
226
|
+
children: w("common.metadata", "Metadata")
|
|
227
|
+
}), /* @__PURE__ */ x("dl", {
|
|
216
228
|
className: "mt-5 space-y-4",
|
|
217
229
|
children: [
|
|
218
|
-
/* @__PURE__ */
|
|
230
|
+
/* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("dt", {
|
|
219
231
|
className: "text-sm font-medium text-[var(--color-text-secondary)]",
|
|
220
|
-
children:
|
|
221
|
-
}), /* @__PURE__ */
|
|
232
|
+
children: w("common.created", "Created")
|
|
233
|
+
}), /* @__PURE__ */ b("dd", {
|
|
222
234
|
className: "mt-1 text-sm text-[var(--color-text-primary)]",
|
|
223
|
-
children:
|
|
235
|
+
children: C(A.createdAt)
|
|
224
236
|
})] }),
|
|
225
|
-
/* @__PURE__ */
|
|
237
|
+
/* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("dt", {
|
|
226
238
|
className: "text-sm font-medium text-[var(--color-text-secondary)]",
|
|
227
|
-
children:
|
|
228
|
-
}), /* @__PURE__ */
|
|
239
|
+
children: w("common.lastUpdated", "Last updated")
|
|
240
|
+
}), /* @__PURE__ */ b("dd", {
|
|
229
241
|
className: "mt-1 text-sm text-[var(--color-text-primary)]",
|
|
230
|
-
children:
|
|
242
|
+
children: C(A.updatedAt)
|
|
231
243
|
})] }),
|
|
232
|
-
/* @__PURE__ */
|
|
244
|
+
/* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("dt", {
|
|
233
245
|
className: "text-sm font-medium text-[var(--color-text-secondary)]",
|
|
234
|
-
children:
|
|
235
|
-
}), /* @__PURE__ */
|
|
246
|
+
children: w("organizations.detail.tenantId", "Tenant ID")
|
|
247
|
+
}), /* @__PURE__ */ b("dd", {
|
|
236
248
|
className: "mt-1 break-all font-mono text-sm text-[var(--color-text-primary)]",
|
|
237
|
-
children:
|
|
249
|
+
children: A.tenantId
|
|
238
250
|
})] })
|
|
239
251
|
]
|
|
240
252
|
})]
|
|
241
253
|
})]
|
|
242
|
-
}) : /* @__PURE__ */
|
|
254
|
+
}) : /* @__PURE__ */ x("section", {
|
|
243
255
|
className: "space-y-4",
|
|
244
|
-
children: [/* @__PURE__ */
|
|
256
|
+
children: [/* @__PURE__ */ x("div", {
|
|
245
257
|
className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",
|
|
246
|
-
children: [/* @__PURE__ */
|
|
258
|
+
children: [/* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("h2", {
|
|
247
259
|
className: "text-lg font-semibold text-[var(--color-text-primary)]",
|
|
248
|
-
children:
|
|
249
|
-
}), /* @__PURE__ */
|
|
260
|
+
children: w("organizations.detail.workspacesTitle", "Organization workspaces")
|
|
261
|
+
}), /* @__PURE__ */ b("p", {
|
|
250
262
|
className: "text-sm text-[var(--color-text-secondary)]",
|
|
251
|
-
children:
|
|
252
|
-
})] }),
|
|
263
|
+
children: w("organizations.detail.workspacesSubtitle", "Create and manage workspaces for this organization.")
|
|
264
|
+
})] }), O(s.WORKSPACE_CREATE) && /* @__PURE__ */ x("button", {
|
|
253
265
|
type: "button",
|
|
254
|
-
onClick: () =>
|
|
266
|
+
onClick: () => E(`${D}/workspaces/new?organizationId=${T}`),
|
|
255
267
|
className: "inline-flex min-h-11 items-center justify-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-4 py-2.5 text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90 active:scale-[0.98]",
|
|
256
|
-
children: [/* @__PURE__ */
|
|
268
|
+
children: [/* @__PURE__ */ b(m, {
|
|
257
269
|
size: 16,
|
|
258
270
|
"aria-hidden": "true"
|
|
259
|
-
}), /* @__PURE__ */
|
|
271
|
+
}), /* @__PURE__ */ b("span", { children: w("workspaces.create.button", "Create Workspace") })]
|
|
260
272
|
})]
|
|
261
|
-
}),
|
|
273
|
+
}), I ? /* @__PURE__ */ b("div", {
|
|
262
274
|
className: "py-8",
|
|
263
|
-
children: /* @__PURE__ */
|
|
264
|
-
}) :
|
|
265
|
-
message:
|
|
275
|
+
children: /* @__PURE__ */ b(i, { message: w("workspaces.list.loading", "Loading workspaces...") })
|
|
276
|
+
}) : L ? /* @__PURE__ */ b(a, {
|
|
277
|
+
message: L.message,
|
|
266
278
|
action: {
|
|
267
|
-
label:
|
|
279
|
+
label: w("common.retry", "Retry"),
|
|
268
280
|
onClick: () => {
|
|
269
|
-
|
|
281
|
+
R();
|
|
270
282
|
}
|
|
271
283
|
}
|
|
272
|
-
}) :
|
|
284
|
+
}) : F.length > 0 ? /* @__PURE__ */ b("div", {
|
|
273
285
|
className: "grid grid-cols-1 gap-4 xl:grid-cols-2",
|
|
274
|
-
children:
|
|
286
|
+
children: F.map((e) => /* @__PURE__ */ b(u, {
|
|
275
287
|
workspace: e,
|
|
276
288
|
showActions: !1,
|
|
277
289
|
onClick: (e) => {
|
|
278
|
-
|
|
290
|
+
E(`${D}/workspaces/${e.id}`);
|
|
279
291
|
}
|
|
280
292
|
}, e.id))
|
|
281
|
-
}) : /* @__PURE__ */
|
|
293
|
+
}) : /* @__PURE__ */ b("div", {
|
|
282
294
|
className: "rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-canvas)] p-6",
|
|
283
|
-
children: /* @__PURE__ */
|
|
284
|
-
icon: /* @__PURE__ */
|
|
295
|
+
children: /* @__PURE__ */ b(o, {
|
|
296
|
+
icon: /* @__PURE__ */ b(m, {
|
|
285
297
|
size: 40,
|
|
286
298
|
"aria-hidden": "true"
|
|
287
299
|
}),
|
|
288
|
-
title:
|
|
289
|
-
description:
|
|
290
|
-
action:
|
|
291
|
-
label:
|
|
292
|
-
onClick: () =>
|
|
300
|
+
title: w("workspaces.list.emptyTitle", "No workspaces yet"),
|
|
301
|
+
description: O(s.WORKSPACE_CREATE) ? w("workspaces.list.emptyDescription", "Create a workspace when this organization is ready to collaborate with teams or projects.") : w("workspaces.list.emptyDescriptionViewer", "No workspaces have been created in this organization yet."),
|
|
302
|
+
action: O(s.WORKSPACE_CREATE) ? {
|
|
303
|
+
label: w("workspaces.create.button", "Create Workspace"),
|
|
304
|
+
onClick: () => E(`${D}/workspaces/new?organizationId=${T}`)
|
|
293
305
|
} : void 0
|
|
294
306
|
})
|
|
295
307
|
})]
|
|
@@ -297,15 +309,15 @@ function C() {
|
|
|
297
309
|
})]
|
|
298
310
|
})]
|
|
299
311
|
})
|
|
300
|
-
}) : /* @__PURE__ */
|
|
312
|
+
}) : /* @__PURE__ */ b("div", {
|
|
301
313
|
className: "min-h-full bg-[var(--color-bg-canvas)] p-6",
|
|
302
|
-
children: /* @__PURE__ */
|
|
314
|
+
children: /* @__PURE__ */ b("div", {
|
|
303
315
|
className: "p-8 text-center text-[var(--color-text-secondary)]",
|
|
304
|
-
children:
|
|
316
|
+
children: w("organizations.detail.noPermission", "You don't have permission to view this organization.")
|
|
305
317
|
})
|
|
306
318
|
});
|
|
307
319
|
}
|
|
308
320
|
//#endregion
|
|
309
|
-
export {
|
|
321
|
+
export { w as OrganizationDetailPage };
|
|
310
322
|
|
|
311
323
|
//# sourceMappingURL=OrganizationDetailPage.js.map
|
package/dist/organization-management/modules/organizations/pages/OrganizationDetailPage.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OrganizationDetailPage.js","names":[],"sources":["../../../../../src/organization-management/modules/organizations/pages/OrganizationDetailPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { ArrowLeft, Briefcase, Building, Edit, Users } from 'lucide-react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { useOrgConsole } from '../../../providers/OrgConsoleProvider';\nimport { useOrganization } from '../hooks/useOrganizations';\nimport { OrganizationStatusBadge } from '../components/OrganizationStatusBadge';\nimport { LoadingState } from '../../../shared/components/feedback/LoadingState';\nimport { ErrorState } from '../../../shared/components/feedback/ErrorState';\nimport { EmptyState } from '../../../shared/components/feedback/EmptyState';\nimport { useWorkspacesByOrganization } from '../../workspaces/hooks/useWorkspaces';\nimport { WorkspaceCard } from '../../workspaces/components/WorkspaceCard';\nimport { PERMISSIONS } from '../../../constants/permissions';\nimport { useTr } from '../../../shared/hooks/useTr';\nimport { useOrganizationPageView } from '../../../hooks/useOrganizationPageView';\n\ntype ActiveTab = 'overview' | 'workspaces';\n\nfunction formatDate(dateString: string) {\n return new Date(dateString).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\nexport function OrganizationDetailPage() {\n const tr = useTr();\n const { id } = useParams<{ id: string }>();\n useOrganizationPageView('organizations.detail', { organizationId: id });\n const { navigate, basePath = '/organizations' } = useOrgConsole();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const { organization, loading, error } = useOrganization(id ?? '');\n const [activeTab, setActiveTab] = useState<ActiveTab>('overview');\n\n const shouldFetchWorkspaces = activeTab === 'workspaces' && Boolean(id);\n const {\n workspaces,\n loading: workspacesLoading,\n error: workspacesError,\n refetch: refetchWorkspaces,\n } = useWorkspacesByOrganization(shouldFetchWorkspaces ? (id ?? '') : '', 50, 0);\n\n const tabItems = useMemo(\n () => [\n { id: 'overview' as const, label: tr('organizations.detail.tab.overview', 'Overview') },\n {\n id: 'workspaces' as const,\n label: `${tr('organizations.detail.tab.workspaces', 'Workspaces')} (${activeTab === 'workspaces' ? workspaces.length : (organization?.workspaceCount ?? 0)})`,\n },\n ],\n [activeTab, organization?.workspaceCount, tr, workspaces.length]\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.ORG_READ)) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] p-6\">\n <div className=\"p-8 text-center text-[var(--color-text-secondary)]\">\n {tr(\n 'organizations.detail.noPermission',\n \"You don't have permission to view this organization.\"\n )}\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\n message={tr('organizations.detail.loading', 'Loading organization details...')}\n />\n </div>\n );\n }\n\n if (error || !organization) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <ErrorState\n message={error?.message || tr('organizations.detail.notFound', 'Organization not found')}\n action={{\n label: tr('organizations.create.back', 'Back to Organizations'),\n onClick: () => navigate(basePath),\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=\"space-y-4\">\n <button\n type=\"button\"\n onClick={() => navigate(basePath)}\n className=\"inline-flex min-h-10 items-center gap-2 text-[var(--color-text-secondary)] transition-all duration-200 hover:text-[var(--color-text-primary)] active:scale-[0.98]\"\n >\n <ArrowLeft size={20} aria-hidden=\"true\" />\n <span className=\"text-sm font-medium\">\n {tr('organizations.create.back', 'Back to Organizations')}\n </span>\n </button>\n\n <div className=\"flex flex-col gap-4 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] p-5 shadow-[var(--shadow-elevation-1)] lg:flex-row lg:items-start lg:justify-between\">\n <div className=\"flex min-w-0 items-start gap-4\">\n <div className=\"flex size-16 items-center justify-center rounded-xl bg-[var(--color-status-info-bgSubtle)] text-[var(--color-status-info-text)]\">\n <Building size={28} aria-hidden=\"true\" />\n </div>\n\n <div className=\"min-w-0 space-y-2\">\n <div className=\"flex flex-wrap items-start gap-3\">\n <h1 className=\"text-3xl font-bold text-[var(--color-text-primary)]\">\n {organization.name}\n </h1>\n <OrganizationStatusBadge status={organization.status} />\n </div>\n <p className=\"break-all font-mono text-sm text-[var(--color-text-secondary)]\">\n /{organization.slug}\n </p>\n {organization.description ? (\n <p className=\"max-w-2xl text-sm text-[var(--color-text-secondary)]\">\n {organization.description}\n </p>\n ) : null}\n </div>\n </div>\n\n <div className=\"flex flex-col gap-3 sm:flex-row\">\n {hasPermission(PERMISSIONS.MEMBER_LIST) && (\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/${id}/members`)}\n className=\"inline-flex min-h-11 items-center justify-center gap-2 rounded-lg border border-[var(--color-border-default)] px-4 py-2.5 text-[var(--color-text-primary)] transition-all duration-200 hover:bg-[var(--color-bg-subtle)]\"\n >\n <Users size={16} aria-hidden=\"true\" />\n <span>\n {hasPermission(PERMISSIONS.MEMBER_INVITE)\n ? tr('organizations.detail.manageMembers', 'Manage Members')\n : tr('organizations.detail.viewMembers', 'View Members')}\n </span>\n </button>\n )}\n {hasPermission(PERMISSIONS.ORG_UPDATE) && (\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/${id}/edit`)}\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 active:scale-[0.98]\"\n >\n <Edit size={16} aria-hidden=\"true\" />\n <span>{tr('organizations.edit.title', 'Edit Organization')}</span>\n </button>\n )}\n </div>\n </div>\n </div>\n\n <div className=\"rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] shadow-[var(--shadow-elevation-1)]\">\n <div className=\"overflow-x-auto border-b border-[var(--color-border-default)]\">\n <div className=\"flex min-w-max gap-2 px-4 pt-4 sm:px-6\">\n {tabItems.map((tabItem) => {\n const isActive = activeTab === tabItem.id;\n return (\n <button\n type=\"button\"\n key={tabItem.id}\n onClick={() => setActiveTab(tabItem.id)}\n className={`inline-flex min-h-11 items-center rounded-t-lg border-b-2 px-4 py-3 text-sm font-medium transition-colors ${\n isActive\n ? 'border-[var(--color-action-primary-bg)] text-[var(--color-action-primary-bg)]'\n : 'border-transparent text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)]'\n }`}\n aria-pressed={isActive}\n >\n {tabItem.label}\n </button>\n );\n })}\n </div>\n </div>\n\n <div className=\"p-4 sm:p-6\">\n {activeTab === 'overview' ? (\n <div className=\"grid grid-cols-1 gap-6 xl:grid-cols-[minmax(0,1fr)_320px]\">\n <section className=\"rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-canvas)] p-5\">\n <h2 className=\"text-lg font-semibold text-[var(--color-text-primary)]\">\n {tr('organizations.detail.detailsSection', 'Organization details')}\n </h2>\n\n <dl className=\"mt-5 grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.name', 'Name')}\n </dt>\n <dd className=\"mt-1 text-sm text-[var(--color-text-primary)]\">\n {organization.name}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.slug', 'Slug')}\n </dt>\n <dd className=\"mt-1 break-all font-mono text-sm text-[var(--color-text-primary)]\">\n {organization.slug}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.status', 'Status')}\n </dt>\n <dd className=\"mt-1\">\n <OrganizationStatusBadge status={organization.status} />\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('organizations.detail.workspaceCount', 'Workspace count')}\n </dt>\n <dd className=\"mt-1 text-sm text-[var(--color-text-primary)]\">\n {organization.workspaceCount ?? 0}\n </dd>\n </div>\n {organization.website ? (\n <div className=\"sm:col-span-2\">\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('organizations.detail.website', 'Website')}\n </dt>\n <dd className=\"mt-1 break-all text-sm\">\n <a\n href={organization.website}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"text-[var(--color-action-primary-bg)] underline-offset-2 hover:underline\"\n >\n {organization.website}\n </a>\n </dd>\n </div>\n ) : null}\n {organization.description ? (\n <div className=\"sm:col-span-2\">\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.description', 'Description')}\n </dt>\n <dd className=\"mt-1 text-sm leading-6 text-[var(--color-text-primary)]\">\n {organization.description}\n </dd>\n </div>\n ) : null}\n </dl>\n </section>\n\n <aside className=\"rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-canvas)] p-5\">\n <h2 className=\"text-lg font-semibold text-[var(--color-text-primary)]\">\n {tr('common.metadata', 'Metadata')}\n </h2>\n\n <dl className=\"mt-5 space-y-4\">\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.created', 'Created')}\n </dt>\n <dd className=\"mt-1 text-sm text-[var(--color-text-primary)]\">\n {formatDate(organization.createdAt)}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.lastUpdated', 'Last updated')}\n </dt>\n <dd className=\"mt-1 text-sm text-[var(--color-text-primary)]\">\n {formatDate(organization.updatedAt)}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('organizations.detail.tenantId', 'Tenant ID')}\n </dt>\n <dd className=\"mt-1 break-all font-mono text-sm text-[var(--color-text-primary)]\">\n {organization.tenantId}\n </dd>\n </div>\n </dl>\n </aside>\n </div>\n ) : (\n <section className=\"space-y-4\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h2 className=\"text-lg font-semibold text-[var(--color-text-primary)]\">\n {tr('organizations.detail.workspacesTitle', 'Organization workspaces')}\n </h2>\n <p className=\"text-sm text-[var(--color-text-secondary)]\">\n {tr(\n 'organizations.detail.workspacesSubtitle',\n 'Create and manage workspaces for this organization.'\n )}\n </p>\n </div>\n\n {hasPermission(PERMISSIONS.WORKSPACE_CREATE) && (\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/workspaces/new?organizationId=${id}`)}\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 active:scale-[0.98]\"\n >\n <Briefcase size={16} aria-hidden=\"true\" />\n <span>{tr('workspaces.create.button', 'Create Workspace')}</span>\n </button>\n )}\n </div>\n\n {workspacesLoading ? (\n <div className=\"py-8\">\n <LoadingState\n message={tr('workspaces.list.loading', 'Loading workspaces...')}\n />\n </div>\n ) : workspacesError ? (\n <ErrorState\n message={workspacesError.message}\n action={{\n label: tr('common.retry', 'Retry'),\n onClick: () => {\n void refetchWorkspaces();\n },\n }}\n />\n ) : workspaces.length > 0 ? (\n <div className=\"grid grid-cols-1 gap-4 xl:grid-cols-2\">\n {workspaces.map((workspace) => (\n <WorkspaceCard\n key={workspace.id}\n workspace={workspace}\n showActions={false}\n onClick={(selectedWorkspace) => {\n navigate(`${basePath}/workspaces/${selectedWorkspace.id}`);\n }}\n />\n ))}\n </div>\n ) : (\n <div className=\"rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-canvas)] p-6\">\n <EmptyState\n icon={<Briefcase size={40} aria-hidden=\"true\" />}\n title={tr('workspaces.list.emptyTitle', 'No workspaces yet')}\n description={\n hasPermission(PERMISSIONS.WORKSPACE_CREATE)\n ? tr(\n 'workspaces.list.emptyDescription',\n 'Create a workspace when this organization is ready to collaborate with teams or projects.'\n )\n : tr(\n 'workspaces.list.emptyDescriptionViewer',\n 'No workspaces have been created in this organization yet.'\n )\n }\n action={\n hasPermission(PERMISSIONS.WORKSPACE_CREATE)\n ? {\n label: tr('workspaces.create.button', 'Create Workspace'),\n onClick: () =>\n navigate(`${basePath}/workspaces/new?organizationId=${id}`),\n }\n : undefined\n }\n />\n </div>\n )}\n </section>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"OrganizationDetailPage.js","names":[],"sources":["../../../../../src/organization-management/modules/organizations/pages/OrganizationDetailPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { ArrowLeft, Briefcase, Building, Edit, UserPlus, Users } from 'lucide-react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { useOrgConsole } from '../../../providers/OrgConsoleProvider';\nimport { useOrganization } from '../hooks/useOrganizations';\nimport { OrganizationStatusBadge } from '../components/OrganizationStatusBadge';\nimport { LoadingState } from '../../../shared/components/feedback/LoadingState';\nimport { ErrorState } from '../../../shared/components/feedback/ErrorState';\nimport { EmptyState } from '../../../shared/components/feedback/EmptyState';\nimport { useWorkspacesByOrganization } from '../../workspaces/hooks/useWorkspaces';\nimport { WorkspaceCard } from '../../workspaces/components/WorkspaceCard';\nimport { PERMISSIONS } from '../../../constants/permissions';\nimport { useTr } from '../../../shared/hooks/useTr';\nimport { useOrganizationPageView } from '../../../hooks/useOrganizationPageView';\n\ntype ActiveTab = 'overview' | 'workspaces';\n\nfunction formatDate(dateString: string) {\n return new Date(dateString).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\nexport function OrganizationDetailPage() {\n const tr = useTr();\n const { id } = useParams<{ id: string }>();\n useOrganizationPageView('organizations.detail', { organizationId: id });\n const { navigate, basePath = '/organizations' } = useOrgConsole();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const { organization, loading, error } = useOrganization(id ?? '');\n const [activeTab, setActiveTab] = useState<ActiveTab>('overview');\n\n const shouldFetchWorkspaces = activeTab === 'workspaces' && Boolean(id);\n const {\n workspaces,\n loading: workspacesLoading,\n error: workspacesError,\n refetch: refetchWorkspaces,\n } = useWorkspacesByOrganization(shouldFetchWorkspaces ? (id ?? '') : '', 50, 0);\n\n const tabItems = useMemo(\n () => [\n { id: 'overview' as const, label: tr('organizations.detail.tab.overview', 'Overview') },\n {\n id: 'workspaces' as const,\n label: `${tr('organizations.detail.tab.workspaces', 'Workspaces')} (${activeTab === 'workspaces' ? workspaces.length : (organization?.workspaceCount ?? 0)})`,\n },\n ],\n [activeTab, organization?.workspaceCount, tr, workspaces.length]\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.ORG_READ)) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] p-6\">\n <div className=\"p-8 text-center text-[var(--color-text-secondary)]\">\n {tr(\n 'organizations.detail.noPermission',\n \"You don't have permission to view this organization.\"\n )}\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\n message={tr('organizations.detail.loading', 'Loading organization details...')}\n />\n </div>\n );\n }\n\n if (error || !organization) {\n return (\n <div className=\"min-h-full bg-[var(--color-bg-canvas)] px-4 py-6 sm:px-6\">\n <ErrorState\n message={error?.message || tr('organizations.detail.notFound', 'Organization not found')}\n action={{\n label: tr('organizations.create.back', 'Back to Organizations'),\n onClick: () => navigate(basePath),\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=\"space-y-4\">\n <button\n type=\"button\"\n onClick={() => navigate(basePath)}\n className=\"inline-flex min-h-10 items-center gap-2 text-[var(--color-text-secondary)] transition-all duration-200 hover:text-[var(--color-text-primary)] active:scale-[0.98]\"\n >\n <ArrowLeft size={20} aria-hidden=\"true\" />\n <span className=\"text-sm font-medium\">\n {tr('organizations.create.back', 'Back to Organizations')}\n </span>\n </button>\n\n <div className=\"flex flex-col gap-4 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] p-5 shadow-[var(--shadow-elevation-1)] lg:flex-row lg:items-start lg:justify-between\">\n <div className=\"flex min-w-0 items-start gap-4\">\n <div className=\"flex size-16 items-center justify-center rounded-xl bg-[var(--color-status-info-bgSubtle)] text-[var(--color-status-info-text)]\">\n <Building size={28} aria-hidden=\"true\" />\n </div>\n\n <div className=\"min-w-0 space-y-2\">\n <div className=\"flex flex-wrap items-start gap-3\">\n <h1 className=\"text-3xl font-bold text-[var(--color-text-primary)]\">\n {organization.name}\n </h1>\n <OrganizationStatusBadge status={organization.status} />\n </div>\n <p className=\"break-all font-mono text-sm text-[var(--color-text-secondary)]\">\n /{organization.slug}\n </p>\n {organization.description ? (\n <p className=\"max-w-2xl text-sm text-[var(--color-text-secondary)]\">\n {organization.description}\n </p>\n ) : null}\n </div>\n </div>\n\n <div className=\"flex flex-col gap-3 sm:flex-row\">\n {hasPermission(PERMISSIONS.MEMBER_LIST) && (\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/${id}/members`)}\n className=\"inline-flex min-h-11 items-center justify-center gap-2 rounded-lg border border-[var(--color-border-default)] px-4 py-2.5 text-[var(--color-text-primary)] transition-all duration-200 hover:bg-[var(--color-bg-subtle)]\"\n >\n <Users size={16} aria-hidden=\"true\" />\n <span>\n {hasPermission(PERMISSIONS.MEMBER_INVITE)\n ? tr('organizations.detail.manageMembers', 'Manage Members')\n : tr('organizations.detail.viewMembers', 'View Members')}\n </span>\n </button>\n )}\n {hasPermission(PERMISSIONS.MEMBER_INVITE) && (\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/${id}/members/invite`)}\n className=\"inline-flex min-h-11 items-center justify-center gap-2 rounded-lg border border-[var(--color-border-default)] px-4 py-2.5 text-[var(--color-text-primary)] transition-all duration-200 hover:bg-[var(--color-bg-subtle)]\"\n >\n <UserPlus size={16} aria-hidden=\"true\" />\n <span>{tr('members.invite.button', 'Invite Member')}</span>\n </button>\n )}\n {hasPermission(PERMISSIONS.ORG_UPDATE) && (\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/${id}/edit`)}\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 active:scale-[0.98]\"\n >\n <Edit size={16} aria-hidden=\"true\" />\n <span>{tr('organizations.edit.title', 'Edit Organization')}</span>\n </button>\n )}\n </div>\n </div>\n </div>\n\n <div className=\"rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] shadow-[var(--shadow-elevation-1)]\">\n <div className=\"overflow-x-auto border-b border-[var(--color-border-default)]\">\n <div className=\"flex min-w-max gap-2 px-4 pt-4 sm:px-6\">\n {tabItems.map((tabItem) => {\n const isActive = activeTab === tabItem.id;\n return (\n <button\n type=\"button\"\n key={tabItem.id}\n onClick={() => setActiveTab(tabItem.id)}\n className={`inline-flex min-h-11 items-center rounded-t-lg border-b-2 px-4 py-3 text-sm font-medium transition-colors ${\n isActive\n ? 'border-[var(--color-action-primary-bg)] text-[var(--color-action-primary-bg)]'\n : 'border-transparent text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)]'\n }`}\n aria-pressed={isActive}\n >\n {tabItem.label}\n </button>\n );\n })}\n </div>\n </div>\n\n <div className=\"p-4 sm:p-6\">\n {activeTab === 'overview' ? (\n <div className=\"grid grid-cols-1 gap-6 xl:grid-cols-[minmax(0,1fr)_320px]\">\n <section className=\"rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-canvas)] p-5\">\n <h2 className=\"text-lg font-semibold text-[var(--color-text-primary)]\">\n {tr('organizations.detail.detailsSection', 'Organization details')}\n </h2>\n\n <dl className=\"mt-5 grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.name', 'Name')}\n </dt>\n <dd className=\"mt-1 text-sm text-[var(--color-text-primary)]\">\n {organization.name}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.slug', 'Slug')}\n </dt>\n <dd className=\"mt-1 break-all font-mono text-sm text-[var(--color-text-primary)]\">\n {organization.slug}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.status', 'Status')}\n </dt>\n <dd className=\"mt-1\">\n <OrganizationStatusBadge status={organization.status} />\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('organizations.detail.workspaceCount', 'Workspace count')}\n </dt>\n <dd className=\"mt-1 text-sm text-[var(--color-text-primary)]\">\n {organization.workspaceCount ?? 0}\n </dd>\n </div>\n {organization.website ? (\n <div className=\"sm:col-span-2\">\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('organizations.detail.website', 'Website')}\n </dt>\n <dd className=\"mt-1 break-all text-sm\">\n <a\n href={organization.website}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"text-[var(--color-action-primary-bg)] underline-offset-2 hover:underline\"\n >\n {organization.website}\n </a>\n </dd>\n </div>\n ) : null}\n {organization.description ? (\n <div className=\"sm:col-span-2\">\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.description', 'Description')}\n </dt>\n <dd className=\"mt-1 text-sm leading-6 text-[var(--color-text-primary)]\">\n {organization.description}\n </dd>\n </div>\n ) : null}\n </dl>\n </section>\n\n <aside className=\"rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-canvas)] p-5\">\n <h2 className=\"text-lg font-semibold text-[var(--color-text-primary)]\">\n {tr('common.metadata', 'Metadata')}\n </h2>\n\n <dl className=\"mt-5 space-y-4\">\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.created', 'Created')}\n </dt>\n <dd className=\"mt-1 text-sm text-[var(--color-text-primary)]\">\n {formatDate(organization.createdAt)}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('common.lastUpdated', 'Last updated')}\n </dt>\n <dd className=\"mt-1 text-sm text-[var(--color-text-primary)]\">\n {formatDate(organization.updatedAt)}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-[var(--color-text-secondary)]\">\n {tr('organizations.detail.tenantId', 'Tenant ID')}\n </dt>\n <dd className=\"mt-1 break-all font-mono text-sm text-[var(--color-text-primary)]\">\n {organization.tenantId}\n </dd>\n </div>\n </dl>\n </aside>\n </div>\n ) : (\n <section className=\"space-y-4\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h2 className=\"text-lg font-semibold text-[var(--color-text-primary)]\">\n {tr('organizations.detail.workspacesTitle', 'Organization workspaces')}\n </h2>\n <p className=\"text-sm text-[var(--color-text-secondary)]\">\n {tr(\n 'organizations.detail.workspacesSubtitle',\n 'Create and manage workspaces for this organization.'\n )}\n </p>\n </div>\n\n {hasPermission(PERMISSIONS.WORKSPACE_CREATE) && (\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/workspaces/new?organizationId=${id}`)}\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 active:scale-[0.98]\"\n >\n <Briefcase size={16} aria-hidden=\"true\" />\n <span>{tr('workspaces.create.button', 'Create Workspace')}</span>\n </button>\n )}\n </div>\n\n {workspacesLoading ? (\n <div className=\"py-8\">\n <LoadingState\n message={tr('workspaces.list.loading', 'Loading workspaces...')}\n />\n </div>\n ) : workspacesError ? (\n <ErrorState\n message={workspacesError.message}\n action={{\n label: tr('common.retry', 'Retry'),\n onClick: () => {\n void refetchWorkspaces();\n },\n }}\n />\n ) : workspaces.length > 0 ? (\n <div className=\"grid grid-cols-1 gap-4 xl:grid-cols-2\">\n {workspaces.map((workspace) => (\n <WorkspaceCard\n key={workspace.id}\n workspace={workspace}\n showActions={false}\n onClick={(selectedWorkspace) => {\n navigate(`${basePath}/workspaces/${selectedWorkspace.id}`);\n }}\n />\n ))}\n </div>\n ) : (\n <div className=\"rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-canvas)] p-6\">\n <EmptyState\n icon={<Briefcase size={40} aria-hidden=\"true\" />}\n title={tr('workspaces.list.emptyTitle', 'No workspaces yet')}\n description={\n hasPermission(PERMISSIONS.WORKSPACE_CREATE)\n ? tr(\n 'workspaces.list.emptyDescription',\n 'Create a workspace when this organization is ready to collaborate with teams or projects.'\n )\n : tr(\n 'workspaces.list.emptyDescriptionViewer',\n 'No workspaces have been created in this organization yet.'\n )\n }\n action={\n hasPermission(PERMISSIONS.WORKSPACE_CREATE)\n ? {\n label: tr('workspaces.create.button', 'Create Workspace'),\n onClick: () =>\n navigate(`${basePath}/workspaces/new?organizationId=${id}`),\n }\n : undefined\n }\n />\n </div>\n )}\n </section>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|