@burdenoff/microfe-workspaces 2026.519.1 → 2026.528.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.
- package/dist/WorkspacesRoot.js +4 -1
- package/dist/WorkspacesRoot.js.map +1 -1
- package/dist/WorkspacesRoutes.js +4 -4
- package/dist/WorkspacesRoutes.js.map +1 -1
- package/dist/components/CreateProjectDialog.js +1 -1
- package/dist/components/CreateProjectDialog.js.map +1 -1
- package/dist/components/CreateWorkspaceDialog.js +2 -2
- package/dist/components/CreateWorkspaceDialog.js.map +1 -1
- package/dist/components/InviteMemberDialog.js +2 -2
- package/dist/components/InviteMemberDialog.js.map +1 -1
- package/dist/components/MemberListItem.js +71 -86
- package/dist/components/MemberListItem.js.map +1 -1
- package/dist/components/ProjectCard.js +12 -10
- package/dist/components/ProjectCard.js.map +1 -1
- package/dist/components/WorkspaceCard.js.map +1 -1
- package/dist/components/WorkspacesErrorBoundary.js +12 -4
- package/dist/components/WorkspacesErrorBoundary.js.map +1 -1
- package/dist/components/tags/ProjectTagsWidget.js +248 -0
- package/dist/components/tags/ProjectTagsWidget.js.map +1 -0
- package/dist/generated/global-operations.js +9 -1
- package/dist/generated/global-operations.js.map +1 -1
- package/dist/hooks/useOrgsWithPermission.js +55 -0
- package/dist/hooks/useOrgsWithPermission.js.map +1 -0
- package/dist/hooks/useWorkspacesEventEmitter.js.map +1 -1
- package/dist/hooks/useWorkspacesPageView.js +6 -4
- package/dist/hooks/useWorkspacesPageView.js.map +1 -1
- package/dist/pages/CreateWorkspacePage.js +173 -149
- package/dist/pages/CreateWorkspacePage.js.map +1 -1
- package/dist/pages/InviteAcceptancePage.js +28 -28
- package/dist/pages/InviteAcceptancePage.js.map +1 -1
- package/dist/pages/MembersListPage.js +380 -352
- package/dist/pages/MembersListPage.js.map +1 -1
- package/dist/pages/ProjectDetailPage.js +96 -97
- package/dist/pages/ProjectDetailPage.js.map +1 -1
- package/dist/pages/ProjectsListPage.js +307 -304
- package/dist/pages/ProjectsListPage.js.map +1 -1
- package/dist/pages/WorkspaceSettingsPage.js +94 -91
- package/dist/pages/WorkspaceSettingsPage.js.map +1 -1
- package/dist/pages/WorkspacesListPage.js +1 -1
- package/dist/pages/WorkspacesListPage.js.map +1 -1
- package/dist/pages/dashboard/DashboardCustomizer.js +68 -68
- package/dist/pages/dashboard/DashboardCustomizer.js.map +1 -1
- package/dist/pages/dashboard/DashboardGrid.js +52 -41
- package/dist/pages/dashboard/DashboardGrid.js.map +1 -1
- package/dist/pages/dashboard/DashboardPage.js +74 -65
- package/dist/pages/dashboard/DashboardPage.js.map +1 -1
- package/dist/pages/dashboard/WidgetWrapper.js +3 -3
- package/dist/pages/dashboard/WidgetWrapper.js.map +1 -1
- package/dist/pages/dashboard/config.js +126 -30
- package/dist/pages/dashboard/config.js.map +1 -1
- package/dist/pages/dashboard/hooks/useDashboardData.js +39 -2
- package/dist/pages/dashboard/hooks/useDashboardData.js.map +1 -1
- package/dist/pages/dashboard/widgets/AgentsWidget.js +109 -0
- package/dist/pages/dashboard/widgets/AgentsWidget.js.map +1 -0
- package/dist/pages/dashboard/widgets/GroupsWidget.js +6 -5
- package/dist/pages/dashboard/widgets/GroupsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/MembersWidget.js +6 -6
- package/dist/pages/dashboard/widgets/MembersWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/ProjectsWidget.js +8 -7
- package/dist/pages/dashboard/widgets/ProjectsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/QuickActionsWidget.js +72 -18
- package/dist/pages/dashboard/widgets/QuickActionsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/RecentActivityWidget.js +3 -3
- package/dist/pages/dashboard/widgets/RecentActivityWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/SessionsWidget.js +78 -0
- package/dist/pages/dashboard/widgets/SessionsWidget.js.map +1 -0
- package/dist/pages/dashboard/widgets/StorageWidget.js +35 -20
- package/dist/pages/dashboard/widgets/StorageWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/TagCloudWidget.js +2 -2
- package/dist/pages/dashboard/widgets/TagCloudWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/TipsWidget.js +81 -22
- package/dist/pages/dashboard/widgets/TipsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/UpcomingEventsWidget.js +6 -5
- package/dist/pages/dashboard/widgets/UpcomingEventsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/VibesWidget.js +64 -0
- package/dist/pages/dashboard/widgets/VibesWidget.js.map +1 -0
- package/dist/pages/dashboard/widgets/WelcomeWidget.js +5 -5
- package/dist/pages/dashboard/widgets/WelcomeWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/WorkflowStatsWidget.js +3 -3
- package/dist/pages/dashboard/widgets/WorkflowStatsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/WorkspacesWidget.js +6 -5
- package/dist/pages/dashboard/widgets/WorkspacesWidget.js.map +1 -1
- package/dist/providers/WorkspacesProvider.js +1 -1
- package/dist/providers/WorkspacesProvider.js.map +1 -1
- package/dist/store/workspacesStore.js.map +1 -1
- package/dist/utils/formatters.js +21 -16
- package/dist/utils/formatters.js.map +1 -1
- package/dist/utils/telemetryError.js +1 -1
- package/dist/utils/telemetryError.js.map +1 -1
- package/package.json +7 -7
- package/dist/WorkspacesRoot.d.ts +0 -35
- package/dist/WorkspacesRoot.d.ts.map +0 -1
- package/dist/WorkspacesRoutes.d.ts +0 -10
- package/dist/WorkspacesRoutes.d.ts.map +0 -1
- package/dist/components/CreateProjectDialog.d.ts +0 -6
- package/dist/components/CreateProjectDialog.d.ts.map +0 -1
- package/dist/components/CreateWorkspaceDialog.d.ts +0 -2
- package/dist/components/CreateWorkspaceDialog.d.ts.map +0 -1
- package/dist/components/InviteMemberDialog.d.ts +0 -7
- package/dist/components/InviteMemberDialog.d.ts.map +0 -1
- package/dist/components/MemberListItem.d.ts +0 -11
- package/dist/components/MemberListItem.d.ts.map +0 -1
- package/dist/components/ProjectCard.d.ts +0 -13
- package/dist/components/ProjectCard.d.ts.map +0 -1
- package/dist/components/WorkspaceCard.d.ts +0 -8
- package/dist/components/WorkspaceCard.d.ts.map +0 -1
- package/dist/components/WorkspacesErrorBoundary.d.ts +0 -27
- package/dist/components/WorkspacesErrorBoundary.d.ts.map +0 -1
- package/dist/components/index.d.ts +0 -8
- package/dist/components/index.d.ts.map +0 -1
- package/dist/constants/permissions.d.ts +0 -33
- package/dist/constants/permissions.d.ts.map +0 -1
- package/dist/generated/global-operations.d.ts +0 -279
- package/dist/generated/global-operations.d.ts.map +0 -1
- package/dist/generated/global-types.d.ts +0 -23527
- package/dist/generated/global-types.d.ts.map +0 -1
- package/dist/generated/wspace-operations.d.ts +0 -2300
- package/dist/generated/wspace-operations.d.ts.map +0 -1
- package/dist/generated/wspace-types.d.ts +0 -57851
- package/dist/generated/wspace-types.d.ts.map +0 -1
- package/dist/hooks/index.d.ts +0 -8
- package/dist/hooks/index.d.ts.map +0 -1
- package/dist/hooks/useMemberMutations.d.ts +0 -61
- package/dist/hooks/useMemberMutations.d.ts.map +0 -1
- package/dist/hooks/useProjectMutations.d.ts +0 -26
- package/dist/hooks/useProjectMutations.d.ts.map +0 -1
- package/dist/hooks/useProjects.d.ts +0 -16
- package/dist/hooks/useProjects.d.ts.map +0 -1
- package/dist/hooks/useScopedNavigation.d.ts +0 -4
- package/dist/hooks/useScopedNavigation.d.ts.map +0 -1
- package/dist/hooks/useTenants.d.ts +0 -13
- package/dist/hooks/useTenants.d.ts.map +0 -1
- package/dist/hooks/useWorkspaceActivity.d.ts +0 -12
- package/dist/hooks/useWorkspaceActivity.d.ts.map +0 -1
- package/dist/hooks/useWorkspaceMembers.d.ts +0 -24
- package/dist/hooks/useWorkspaceMembers.d.ts.map +0 -1
- package/dist/hooks/useWorkspaceMutations.d.ts +0 -36
- package/dist/hooks/useWorkspaceMutations.d.ts.map +0 -1
- package/dist/hooks/useWorkspacePermissions.d.ts +0 -29
- package/dist/hooks/useWorkspacePermissions.d.ts.map +0 -1
- package/dist/hooks/useWorkspaceRoles.d.ts +0 -8
- package/dist/hooks/useWorkspaceRoles.d.ts.map +0 -1
- package/dist/hooks/useWorkspaces.d.ts +0 -21
- package/dist/hooks/useWorkspaces.d.ts.map +0 -1
- package/dist/hooks/useWorkspacesEventEmitter.d.ts +0 -18
- package/dist/hooks/useWorkspacesEventEmitter.d.ts.map +0 -1
- package/dist/hooks/useWorkspacesPageView.d.ts +0 -27
- package/dist/hooks/useWorkspacesPageView.d.ts.map +0 -1
- package/dist/index.d.ts +0 -33
- package/dist/index.d.ts.map +0 -1
- package/dist/pages/ActivityListPage.d.ts +0 -2
- package/dist/pages/ActivityListPage.d.ts.map +0 -1
- package/dist/pages/CreateWorkspacePage.d.ts +0 -2
- package/dist/pages/CreateWorkspacePage.d.ts.map +0 -1
- package/dist/pages/InviteAcceptancePage.d.ts +0 -6
- package/dist/pages/InviteAcceptancePage.d.ts.map +0 -1
- package/dist/pages/MembersListPage.d.ts +0 -2
- package/dist/pages/MembersListPage.d.ts.map +0 -1
- package/dist/pages/ProjectDetailPage.d.ts +0 -2
- package/dist/pages/ProjectDetailPage.d.ts.map +0 -1
- package/dist/pages/ProjectsListPage.d.ts +0 -2
- package/dist/pages/ProjectsListPage.d.ts.map +0 -1
- package/dist/pages/WorkspaceDetailPage.d.ts +0 -2
- package/dist/pages/WorkspaceDetailPage.d.ts.map +0 -1
- package/dist/pages/WorkspaceSettingsPage.d.ts +0 -2
- package/dist/pages/WorkspaceSettingsPage.d.ts.map +0 -1
- package/dist/pages/WorkspacesListPage.d.ts +0 -2
- package/dist/pages/WorkspacesListPage.d.ts.map +0 -1
- package/dist/pages/dashboard/DashboardCustomizer.d.ts +0 -12
- package/dist/pages/dashboard/DashboardCustomizer.d.ts.map +0 -1
- package/dist/pages/dashboard/DashboardGrid.d.ts +0 -8
- package/dist/pages/dashboard/DashboardGrid.d.ts.map +0 -1
- package/dist/pages/dashboard/DashboardPage.d.ts +0 -14
- package/dist/pages/dashboard/DashboardPage.d.ts.map +0 -1
- package/dist/pages/dashboard/WidgetWrapper.d.ts +0 -17
- package/dist/pages/dashboard/WidgetWrapper.d.ts.map +0 -1
- package/dist/pages/dashboard/config.d.ts +0 -9
- package/dist/pages/dashboard/config.d.ts.map +0 -1
- package/dist/pages/dashboard/hooks/useDashboardData.d.ts +0 -9
- package/dist/pages/dashboard/hooks/useDashboardData.d.ts.map +0 -1
- package/dist/pages/dashboard/hooks/useDashboardPreferences.d.ts +0 -4
- package/dist/pages/dashboard/hooks/useDashboardPreferences.d.ts.map +0 -1
- package/dist/pages/dashboard/types.d.ts +0 -145
- package/dist/pages/dashboard/types.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/GroupsWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/GroupsWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/MembersWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/MembersWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/ProjectsWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/ProjectsWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/QuickActionsWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/QuickActionsWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/RecentActivityWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/RecentActivityWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/StorageWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/StorageWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/SystemHealthWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/SystemHealthWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/SystemHealthWidget.js +0 -59
- package/dist/pages/dashboard/widgets/SystemHealthWidget.js.map +0 -1
- package/dist/pages/dashboard/widgets/TagCloudWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/TagCloudWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/TipsWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/TipsWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/UpcomingEventsWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/UpcomingEventsWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/WelcomeWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/WelcomeWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/WorkflowStatsWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/WorkflowStatsWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/WorkspacesWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/WorkspacesWidget.d.ts.map +0 -1
- package/dist/providers/WorkspacesProvider.d.ts +0 -13
- package/dist/providers/WorkspacesProvider.d.ts.map +0 -1
- package/dist/store/workspacesStore.d.ts +0 -82
- package/dist/store/workspacesStore.d.ts.map +0 -1
- package/dist/types/index.d.ts +0 -280
- package/dist/types/index.d.ts.map +0 -1
- package/dist/utils/formatters.d.ts +0 -60
- package/dist/utils/formatters.d.ts.map +0 -1
- package/dist/utils/i18n.d.ts +0 -13
- package/dist/utils/i18n.d.ts.map +0 -1
- package/dist/utils/index.d.ts +0 -3
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/nativeBridge.d.ts +0 -3
- package/dist/utils/nativeBridge.d.ts.map +0 -1
- package/dist/utils/projectTags.d.ts +0 -6
- package/dist/utils/projectTags.d.ts.map +0 -1
- package/dist/utils/slug.d.ts +0 -13
- package/dist/utils/slug.d.ts.map +0 -1
- package/dist/utils/telemetryError.d.ts +0 -2
- package/dist/utils/telemetryError.d.ts.map +0 -1
- package/dist/utils/tokenHelpers.d.ts +0 -114
- package/dist/utils/tokenHelpers.d.ts.map +0 -1
|
@@ -1,29 +1,30 @@
|
|
|
1
1
|
import { useWorkspacesContext as e } from "../providers/WorkspacesProvider.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { useEffect as
|
|
9
|
-
import { AlertCircle as
|
|
10
|
-
import { jsx as
|
|
11
|
-
import { Button as
|
|
12
|
-
import { Link as
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
2
|
+
import { tWithFallback as t } from "../utils/i18n.js";
|
|
3
|
+
import { useWorkspacesPageView as ee } from "../hooks/useWorkspacesPageView.js";
|
|
4
|
+
import { useCreateWorkspace as n } from "../hooks/useWorkspaceMutations.js";
|
|
5
|
+
import { useMyOrganizations as r, useMyTenants as i } from "../hooks/useTenants.js";
|
|
6
|
+
import { generateSlug as a } from "../utils/slug.js";
|
|
7
|
+
import { useOrgsWithPermission as o } from "../hooks/useOrgsWithPermission.js";
|
|
8
|
+
import { useEffect as s, useMemo as c } from "react";
|
|
9
|
+
import { AlertCircle as l, ArrowLeft as u } from "lucide-react";
|
|
10
|
+
import { jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
11
|
+
import { Button as p, Card as te, CardContent as m, CardDescription as h, CardHeader as g, CardTitle as _, Skeleton as v } from "@burdenoff/fe-libs/ui";
|
|
12
|
+
import { Link as y, useNavigate as b } from "react-router-dom";
|
|
13
|
+
import { useUpgradePrompt as x } from "@burdenoff/fe-libs/shared/hooks";
|
|
14
|
+
import { AccessDenied as S, UpgradeInlineBanner as C } from "@burdenoff/fe-libs/shared/components";
|
|
15
|
+
import { useI18n as w } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
16
|
+
import { useForm as T, z as E } from "@burdenoff/fe-libs/form";
|
|
16
17
|
//#region src/pages/CreateWorkspacePage.tsx
|
|
17
|
-
function
|
|
18
|
-
|
|
19
|
-
let { t: O } =
|
|
20
|
-
name:
|
|
21
|
-
slug:
|
|
22
|
-
tenantId:
|
|
23
|
-
organizationId:
|
|
24
|
-
type:
|
|
25
|
-
}), [
|
|
26
|
-
schema:
|
|
18
|
+
function D() {
|
|
19
|
+
ee("workspaces.create");
|
|
20
|
+
let { t: D } = w(), { isFree: O, approachingLimits: k, plan: ne } = x({ resource: "workspaces" }), A = k[0], j = !!A && typeof A.limit == "number" && A.current >= A.limit, re = O && !!A, M = c(() => E.object({
|
|
21
|
+
name: E.string().min(2, t(D, "createWorkspace.validation.nameMin", "Name must be at least 2 characters")).max(100),
|
|
22
|
+
slug: E.string().min(2, t(D, "createWorkspace.validation.slugMin", "Slug must be at least 2 characters")).max(50).regex(/^[a-z0-9-]+$/, t(D, "createWorkspace.validation.slugFormat", "Slug can only contain lowercase letters, numbers, and hyphens")),
|
|
23
|
+
tenantId: E.string().min(1, t(D, "createWorkspace.validation.tenantRequired", "Please select a tenant")),
|
|
24
|
+
organizationId: E.string().min(1, t(D, "createWorkspace.validation.organizationRequired", "Please select an organization")),
|
|
25
|
+
type: E.enum(["TEAM", "PERSONAL"]).optional()
|
|
26
|
+
}), [D]), N = b(), { basePath: P = "/" } = e(), { mutate: F, isPending: I } = n(), { data: L, isLoading: R, error: z } = i(), { data: B, isLoading: V, error: H } = r(), U = c(() => L?.items ?? [], [L]), W = c(() => B?.items ?? [], [B]), G = c(() => U.find((e) => e.type === "SHARED" || e.slug === "burdenoff-shared")?.id ?? U[0]?.id ?? "", [U]), K = T({
|
|
27
|
+
schema: M,
|
|
27
28
|
defaultValues: {
|
|
28
29
|
name: "",
|
|
29
30
|
slug: "",
|
|
@@ -31,234 +32,257 @@ function O() {
|
|
|
31
32
|
organizationId: "",
|
|
32
33
|
type: "TEAM"
|
|
33
34
|
}
|
|
34
|
-
}),
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
}), q = K.watch("tenantId"), J = K.watch("name"), { allowedIds: Y, loading: X, isError: Z } = o(c(() => W.map((e) => e.id), [W]), "workspace", "create"), Q = c(() => q ? W.filter((e) => e.tenantId === q) : [], [q, W]), $ = c(() => Z ? Q : Q.filter((e) => Y.has(e.id)), [
|
|
36
|
+
Q,
|
|
37
|
+
Y,
|
|
38
|
+
Z
|
|
39
|
+
]);
|
|
40
|
+
s(() => {
|
|
41
|
+
K.setValue("slug", J ? a(J) : "");
|
|
42
|
+
}, [J, K]), s(() => {
|
|
43
|
+
K.setValue("organizationId", "");
|
|
44
|
+
}, [q, K]), s(() => {
|
|
45
|
+
!K.getValues("tenantId") && G && K.setValue("tenantId", G, {
|
|
41
46
|
shouldDirty: !1,
|
|
42
47
|
shouldTouch: !1
|
|
43
48
|
});
|
|
44
|
-
}, [
|
|
45
|
-
let e =
|
|
46
|
-
|
|
49
|
+
}, [G, K]), s(() => {
|
|
50
|
+
let e = K.getValues("organizationId");
|
|
51
|
+
!$.some((t) => t.id === e) && $[0]?.id && K.setValue("organizationId", $[0].id, {
|
|
47
52
|
shouldDirty: !1,
|
|
48
53
|
shouldTouch: !1
|
|
49
54
|
});
|
|
50
|
-
}, [K
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
})]
|
|
68
|
-
}),
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
55
|
+
}, [$, K]);
|
|
56
|
+
let ie = (e) => {
|
|
57
|
+
F({
|
|
58
|
+
name: e.name,
|
|
59
|
+
slug: e.slug,
|
|
60
|
+
tenantId: e.tenantId,
|
|
61
|
+
organizationId: e.organizationId,
|
|
62
|
+
type: e.type
|
|
63
|
+
}, { onSuccess: (e) => {
|
|
64
|
+
N(`${P}/${e.id}`);
|
|
65
|
+
} });
|
|
66
|
+
}, ae = Y.size > 0, oe = R || V || X, se = !z && !H && W.length > 0;
|
|
67
|
+
return !oe && !Z && se && !ae ? /* @__PURE__ */ f("div", {
|
|
68
|
+
className: "p-6",
|
|
69
|
+
children: [/* @__PURE__ */ f(y, {
|
|
70
|
+
to: `${P}/list`,
|
|
71
|
+
className: "inline-flex items-center gap-2 text-muted-foreground hover:text-foreground transition-colors mb-6",
|
|
72
|
+
children: [/* @__PURE__ */ d(u, { size: 20 }), t(D, "createWorkspace.backToWorkspaces", "Back to Workspaces")]
|
|
73
|
+
}), /* @__PURE__ */ d(S, {
|
|
74
|
+
variant: "card",
|
|
75
|
+
title: t(D, "createWorkspace.permissionRequiredTitle", "Permission Required"),
|
|
76
|
+
description: t(D, "createWorkspace.permissionRequiredDescription", "You don't have permission to create workspaces in any of your organizations."),
|
|
77
|
+
details: t(D, "createWorkspace.permissionRequiredDetails", "Required: workspace:create"),
|
|
78
|
+
primaryAction: {
|
|
79
|
+
label: t(D, "createWorkspace.goBack", "Go Back"),
|
|
80
|
+
onClick: () => N(`${P}/list`)
|
|
81
|
+
}
|
|
82
|
+
})]
|
|
83
|
+
}) : /* @__PURE__ */ f("div", {
|
|
84
|
+
className: "space-y-4 sm:space-y-6 p-3 sm:p-6",
|
|
85
|
+
children: [
|
|
86
|
+
/* @__PURE__ */ f(y, {
|
|
87
|
+
to: `${P}/list`,
|
|
73
88
|
className: "inline-flex items-center gap-2 text-muted-foreground hover:text-foreground transition-colors",
|
|
74
|
-
children: [/* @__PURE__ */
|
|
75
|
-
}),
|
|
89
|
+
children: [/* @__PURE__ */ d(u, { size: 20 }), t(D, "createWorkspace.backToWorkspaces", "Back to Workspaces")]
|
|
90
|
+
}),
|
|
91
|
+
re && /* @__PURE__ */ d("div", {
|
|
92
|
+
className: "max-w-2xl mx-auto w-full",
|
|
93
|
+
children: /* @__PURE__ */ d(C, {
|
|
94
|
+
resource: "workspaces",
|
|
95
|
+
current: A.current,
|
|
96
|
+
limit: A.limit ?? void 0,
|
|
97
|
+
severity: j ? "critical" : void 0,
|
|
98
|
+
message: j ? t(D, "createWorkspace.upgradeCapMessage", `You've used all workspaces in the ${ne?.planName ?? "free"} plan.`) : t(D, "createWorkspace.upgradeApproachingMessage", "Upgrade to create more workspaces.")
|
|
99
|
+
})
|
|
100
|
+
}),
|
|
101
|
+
/* @__PURE__ */ f(te, {
|
|
76
102
|
className: "max-w-2xl mx-auto",
|
|
77
|
-
children: [/* @__PURE__ */
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
A(`${j}/${e.id}`);
|
|
87
|
-
} });
|
|
88
|
-
}),
|
|
103
|
+
children: [/* @__PURE__ */ f(g, { children: [/* @__PURE__ */ d(_, { children: t(D, "createWorkspace.title", "Create New Workspace") }), /* @__PURE__ */ d(h, { children: t(D, "createWorkspace.subtitle", "Set up a new workspace for your team or personal use") })] }), /* @__PURE__ */ f(m, { children: [Z && /* @__PURE__ */ f("div", {
|
|
104
|
+
role: "alert",
|
|
105
|
+
className: "mb-4 flex items-start gap-2 rounded-md border border-warning/30 bg-warning/10 p-3 text-sm text-foreground",
|
|
106
|
+
children: [/* @__PURE__ */ d(l, {
|
|
107
|
+
size: 16,
|
|
108
|
+
className: "mt-0.5 shrink-0 text-warning"
|
|
109
|
+
}), /* @__PURE__ */ d("span", { children: t(D, "createWorkspace.permissionCheckUnavailable", "We couldn't verify your workspace-create permissions just now, so the organization list isn't filtered. If you submit and don't have access, the request will be rejected and you can retry.") })]
|
|
110
|
+
}), /* @__PURE__ */ f("form", {
|
|
111
|
+
onSubmit: K.handleSubmit(ie),
|
|
89
112
|
className: "space-y-6",
|
|
90
113
|
children: [
|
|
91
|
-
/* @__PURE__ */
|
|
114
|
+
/* @__PURE__ */ f("div", {
|
|
92
115
|
className: "space-y-2",
|
|
93
116
|
children: [
|
|
94
|
-
/* @__PURE__ */
|
|
117
|
+
/* @__PURE__ */ d("label", {
|
|
95
118
|
htmlFor: "workspace-name",
|
|
96
119
|
className: "text-sm font-medium text-foreground",
|
|
97
|
-
children:
|
|
120
|
+
children: t(D, "createWorkspace.nameLabel", "Workspace Name *")
|
|
98
121
|
}),
|
|
99
|
-
/* @__PURE__ */
|
|
122
|
+
/* @__PURE__ */ d("input", {
|
|
100
123
|
id: "workspace-name",
|
|
101
|
-
placeholder:
|
|
124
|
+
placeholder: t(D, "createWorkspace.namePlaceholder", "My Workspace"),
|
|
102
125
|
className: "h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground",
|
|
103
|
-
...
|
|
126
|
+
...K.register("name")
|
|
104
127
|
}),
|
|
105
|
-
/* @__PURE__ */
|
|
128
|
+
/* @__PURE__ */ d("p", {
|
|
106
129
|
className: "text-xs text-muted-foreground",
|
|
107
|
-
children:
|
|
130
|
+
children: t(D, "createWorkspace.nameHint", "A descriptive name for your workspace")
|
|
108
131
|
}),
|
|
109
|
-
|
|
132
|
+
K.formState.errors.name?.message && /* @__PURE__ */ d("p", {
|
|
110
133
|
className: "text-sm text-destructive",
|
|
111
|
-
children:
|
|
134
|
+
children: K.formState.errors.name.message
|
|
112
135
|
})
|
|
113
136
|
]
|
|
114
137
|
}),
|
|
115
|
-
/* @__PURE__ */
|
|
138
|
+
/* @__PURE__ */ f("div", {
|
|
116
139
|
className: "space-y-2",
|
|
117
140
|
children: [
|
|
118
|
-
/* @__PURE__ */
|
|
141
|
+
/* @__PURE__ */ d("label", {
|
|
119
142
|
htmlFor: "workspace-slug",
|
|
120
143
|
className: "text-sm font-medium text-foreground",
|
|
121
|
-
children:
|
|
144
|
+
children: t(D, "createWorkspace.slugLabel", "Slug *")
|
|
122
145
|
}),
|
|
123
|
-
/* @__PURE__ */
|
|
146
|
+
/* @__PURE__ */ d("input", {
|
|
124
147
|
id: "workspace-slug",
|
|
125
|
-
placeholder:
|
|
148
|
+
placeholder: t(D, "createWorkspace.slugPlaceholder", "my-workspace"),
|
|
126
149
|
className: "h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground",
|
|
127
|
-
...
|
|
150
|
+
...K.register("slug")
|
|
128
151
|
}),
|
|
129
|
-
/* @__PURE__ */
|
|
152
|
+
/* @__PURE__ */ d("p", {
|
|
130
153
|
className: "text-xs text-muted-foreground",
|
|
131
|
-
children:
|
|
154
|
+
children: t(D, "createWorkspace.slugHint", "URL-friendly identifier (auto-generated, but you can edit it)")
|
|
132
155
|
}),
|
|
133
|
-
|
|
156
|
+
K.formState.errors.slug?.message && /* @__PURE__ */ d("p", {
|
|
134
157
|
className: "text-sm text-destructive",
|
|
135
|
-
children:
|
|
158
|
+
children: K.formState.errors.slug.message
|
|
136
159
|
})
|
|
137
160
|
]
|
|
138
161
|
}),
|
|
139
|
-
/* @__PURE__ */
|
|
162
|
+
/* @__PURE__ */ f("div", {
|
|
140
163
|
className: "space-y-2",
|
|
141
164
|
children: [
|
|
142
|
-
/* @__PURE__ */
|
|
165
|
+
/* @__PURE__ */ d("label", {
|
|
143
166
|
htmlFor: "workspace-tenant",
|
|
144
167
|
className: "text-sm font-medium text-foreground",
|
|
145
|
-
children:
|
|
168
|
+
children: t(D, "createWorkspace.tenantLabel", "Tenant *")
|
|
146
169
|
}),
|
|
147
|
-
|
|
170
|
+
R ? /* @__PURE__ */ d(v, { className: "h-10 w-full" }) : z ? /* @__PURE__ */ f("div", {
|
|
148
171
|
className: "flex items-center gap-2 text-sm text-destructive",
|
|
149
|
-
children: [/* @__PURE__ */
|
|
150
|
-
}) :
|
|
172
|
+
children: [/* @__PURE__ */ d(l, { size: 16 }), t(D, "createWorkspace.failedToLoadTenants", "Failed to load tenants")]
|
|
173
|
+
}) : U.length === 0 ? /* @__PURE__ */ d("div", {
|
|
151
174
|
className: "text-sm text-muted-foreground",
|
|
152
|
-
children:
|
|
153
|
-
}) : /* @__PURE__ */
|
|
175
|
+
children: t(D, "createWorkspace.noTenantsAvailable", "No tenants available. Contact your administrator.")
|
|
176
|
+
}) : /* @__PURE__ */ f("select", {
|
|
154
177
|
id: "workspace-tenant",
|
|
155
178
|
className: "h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground",
|
|
156
|
-
...
|
|
157
|
-
children: [/* @__PURE__ */
|
|
179
|
+
...K.register("tenantId"),
|
|
180
|
+
children: [/* @__PURE__ */ d("option", {
|
|
158
181
|
value: "",
|
|
159
|
-
children:
|
|
160
|
-
}),
|
|
182
|
+
children: t(D, "createWorkspace.selectTenantPlaceholder", "Select a tenant")
|
|
183
|
+
}), U.map((e) => /* @__PURE__ */ d("option", {
|
|
161
184
|
value: e.id,
|
|
162
185
|
children: e.name
|
|
163
186
|
}, e.id))]
|
|
164
187
|
}),
|
|
165
|
-
/* @__PURE__ */
|
|
188
|
+
/* @__PURE__ */ d("p", {
|
|
166
189
|
className: "text-xs text-muted-foreground",
|
|
167
|
-
children:
|
|
190
|
+
children: t(D, "createWorkspace.tenantHint", "Select which tenant this workspace belongs to")
|
|
168
191
|
}),
|
|
169
|
-
|
|
192
|
+
K.formState.errors.tenantId?.message && /* @__PURE__ */ d("p", {
|
|
170
193
|
className: "text-sm text-destructive",
|
|
171
|
-
children:
|
|
194
|
+
children: K.formState.errors.tenantId.message
|
|
172
195
|
})
|
|
173
196
|
]
|
|
174
197
|
}),
|
|
175
|
-
/* @__PURE__ */
|
|
198
|
+
/* @__PURE__ */ f("div", {
|
|
176
199
|
className: "space-y-2",
|
|
177
200
|
children: [
|
|
178
|
-
/* @__PURE__ */
|
|
201
|
+
/* @__PURE__ */ d("label", {
|
|
179
202
|
htmlFor: "workspace-organization",
|
|
180
203
|
className: "text-sm font-medium text-foreground",
|
|
181
|
-
children:
|
|
204
|
+
children: t(D, "createWorkspace.organizationLabel", "Organization *")
|
|
182
205
|
}),
|
|
183
|
-
|
|
206
|
+
V || X ? /* @__PURE__ */ d(v, { className: "h-10 w-full" }) : H ? /* @__PURE__ */ f("div", {
|
|
184
207
|
className: "flex items-center gap-2 text-sm text-destructive",
|
|
185
|
-
children: [/* @__PURE__ */
|
|
186
|
-
}) :
|
|
208
|
+
children: [/* @__PURE__ */ d(l, { size: 16 }), t(D, "createWorkspace.failedToLoadOrganizations", "Failed to load organizations")]
|
|
209
|
+
}) : q ? $.length === 0 ? /* @__PURE__ */ d("div", {
|
|
187
210
|
className: "text-sm text-muted-foreground",
|
|
188
|
-
children:
|
|
189
|
-
}) : /* @__PURE__ */
|
|
211
|
+
children: t(D, "createWorkspace.noOrganizationsFound", "No organizations found for this tenant")
|
|
212
|
+
}) : /* @__PURE__ */ f("select", {
|
|
190
213
|
id: "workspace-organization",
|
|
191
214
|
className: "h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground",
|
|
192
|
-
disabled: !
|
|
193
|
-
...
|
|
194
|
-
children: [/* @__PURE__ */
|
|
215
|
+
disabled: !q,
|
|
216
|
+
...K.register("organizationId"),
|
|
217
|
+
children: [/* @__PURE__ */ d("option", {
|
|
195
218
|
value: "",
|
|
196
|
-
children:
|
|
197
|
-
}),
|
|
219
|
+
children: t(D, "createWorkspace.selectOrganizationPlaceholder", "Select an organization")
|
|
220
|
+
}), $.map((e) => /* @__PURE__ */ d("option", {
|
|
198
221
|
value: e.id,
|
|
199
222
|
children: e.name
|
|
200
223
|
}, e.id))]
|
|
201
|
-
}) : /* @__PURE__ */
|
|
224
|
+
}) : /* @__PURE__ */ d("div", {
|
|
202
225
|
className: "text-sm text-muted-foreground",
|
|
203
|
-
children:
|
|
226
|
+
children: t(D, "createWorkspace.selectTenantFirst", "Please select a tenant first")
|
|
204
227
|
}),
|
|
205
|
-
/* @__PURE__ */
|
|
228
|
+
/* @__PURE__ */ d("p", {
|
|
206
229
|
className: "text-xs text-muted-foreground",
|
|
207
|
-
children:
|
|
230
|
+
children: t(D, "createWorkspace.organizationHint", "Select which organization owns this workspace")
|
|
208
231
|
}),
|
|
209
|
-
|
|
232
|
+
K.formState.errors.organizationId?.message && /* @__PURE__ */ d("p", {
|
|
210
233
|
className: "text-sm text-destructive",
|
|
211
|
-
children:
|
|
234
|
+
children: K.formState.errors.organizationId.message
|
|
212
235
|
})
|
|
213
236
|
]
|
|
214
237
|
}),
|
|
215
|
-
/* @__PURE__ */
|
|
238
|
+
/* @__PURE__ */ f("div", {
|
|
216
239
|
className: "space-y-2",
|
|
217
240
|
children: [
|
|
218
|
-
/* @__PURE__ */
|
|
241
|
+
/* @__PURE__ */ d("label", {
|
|
219
242
|
htmlFor: "workspace-type",
|
|
220
243
|
className: "text-sm font-medium text-foreground",
|
|
221
|
-
children:
|
|
244
|
+
children: t(D, "createWorkspace.typeLabel", "Workspace Type")
|
|
222
245
|
}),
|
|
223
|
-
/* @__PURE__ */
|
|
246
|
+
/* @__PURE__ */ f("select", {
|
|
224
247
|
id: "workspace-type",
|
|
225
248
|
className: "h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground",
|
|
226
|
-
...
|
|
227
|
-
children: [/* @__PURE__ */
|
|
249
|
+
...K.register("type"),
|
|
250
|
+
children: [/* @__PURE__ */ d("option", {
|
|
228
251
|
value: "TEAM",
|
|
229
|
-
children:
|
|
230
|
-
}), /* @__PURE__ */
|
|
252
|
+
children: t(D, "createWorkspace.typeTeam", "Team Workspace")
|
|
253
|
+
}), /* @__PURE__ */ d("option", {
|
|
231
254
|
value: "PERSONAL",
|
|
232
|
-
children:
|
|
255
|
+
children: t(D, "createWorkspace.typePersonal", "Personal Workspace")
|
|
233
256
|
})]
|
|
234
257
|
}),
|
|
235
|
-
/* @__PURE__ */
|
|
258
|
+
/* @__PURE__ */ d("p", {
|
|
236
259
|
className: "text-xs text-muted-foreground",
|
|
237
|
-
children:
|
|
260
|
+
children: t(D, "createWorkspace.typeHint", "Choose between a collaborative workspace or a personal one")
|
|
238
261
|
})
|
|
239
262
|
]
|
|
240
263
|
}),
|
|
241
|
-
/* @__PURE__ */
|
|
264
|
+
/* @__PURE__ */ f("div", {
|
|
242
265
|
className: "flex justify-end gap-3 pt-4",
|
|
243
|
-
children: [/* @__PURE__ */
|
|
266
|
+
children: [/* @__PURE__ */ d(p, {
|
|
244
267
|
type: "button",
|
|
245
268
|
variant: "outline",
|
|
246
|
-
onClick: () =>
|
|
247
|
-
disabled:
|
|
248
|
-
children:
|
|
249
|
-
}), /* @__PURE__ */
|
|
269
|
+
onClick: () => N(`${P}/list`),
|
|
270
|
+
disabled: I,
|
|
271
|
+
children: t(D, "createWorkspace.cancel", "Cancel")
|
|
272
|
+
}), /* @__PURE__ */ d(p, {
|
|
250
273
|
type: "submit",
|
|
251
|
-
disabled:
|
|
252
|
-
|
|
274
|
+
disabled: I || R || V || X || j,
|
|
275
|
+
title: j ? t(D, "createWorkspace.disabledAtCap", "Workspace limit reached — upgrade your plan to create more.") : void 0,
|
|
276
|
+
children: I ? t(D, "createWorkspace.creating", "Creating...") : t(D, "createWorkspace.submit", "Create Workspace")
|
|
253
277
|
})]
|
|
254
278
|
})
|
|
255
279
|
]
|
|
256
|
-
}) })]
|
|
257
|
-
})
|
|
258
|
-
|
|
280
|
+
})] })]
|
|
281
|
+
})
|
|
282
|
+
]
|
|
259
283
|
});
|
|
260
284
|
}
|
|
261
285
|
//#endregion
|
|
262
|
-
export {
|
|
286
|
+
export { D as CreateWorkspacePage };
|
|
263
287
|
|
|
264
288
|
//# sourceMappingURL=CreateWorkspacePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CreateWorkspacePage.js","names":[],"sources":["../../src/pages/CreateWorkspacePage.tsx"],"sourcesContent":["import { useEffect, useMemo } from 'react';\nimport { ArrowLeft, AlertCircle } from 'lucide-react';\nimport { Link, useNavigate } from 'react-router-dom';\nimport {\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n Skeleton,\n} from '@burdenoff/fe-libs/ui';\nimport { useForm, z } from '@burdenoff/fe-libs/form';\nimport { PermissionGate, AccessDenied } from '@burdenoff/fe-libs/shared/components';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { WORKSPACE_PERMISSIONS } from '../constants/permissions';\nimport { useCreateWorkspace } from '../hooks/useWorkspaceMutations';\nimport { useMyTenants, useMyOrganizations } from '../hooks/useTenants';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport { useWorkspacesPageView } from '../hooks/useWorkspacesPageView';\nimport { generateSlug } from '../utils/slug';\nimport { tWithFallback } from '../utils/i18n';\n\ntype CreateWorkspaceFormData = {\n name: string;\n slug: string;\n tenantId: string;\n organizationId: string;\n type?: 'TEAM' | 'PERSONAL';\n};\n\nexport function CreateWorkspacePage() {\n useWorkspacesPageView('workspaces.create');\n const { t } = useI18n();\n const createWorkspaceSchema = useMemo(\n () =>\n z.object({\n name: z\n .string()\n .min(\n 2,\n tWithFallback(\n t,\n 'createWorkspace.validation.nameMin',\n 'Name must be at least 2 characters'\n )\n )\n .max(100),\n slug: z\n .string()\n .min(\n 2,\n tWithFallback(\n t,\n 'createWorkspace.validation.slugMin',\n 'Slug must be at least 2 characters'\n )\n )\n .max(50)\n .regex(\n /^[a-z0-9-]+$/,\n tWithFallback(\n t,\n 'createWorkspace.validation.slugFormat',\n 'Slug can only contain lowercase letters, numbers, and hyphens'\n )\n ),\n tenantId: z\n .string()\n .min(\n 1,\n tWithFallback(t, 'createWorkspace.validation.tenantRequired', 'Please select a tenant')\n ),\n organizationId: z\n .string()\n .min(\n 1,\n tWithFallback(\n t,\n 'createWorkspace.validation.organizationRequired',\n 'Please select an organization'\n )\n ),\n type: z.enum(['TEAM', 'PERSONAL']).optional(),\n }),\n [t]\n );\n\n const navigate = useNavigate();\n const { basePath = '/' } = useWorkspacesContext();\n const { mutate: createWorkspace, isPending } = useCreateWorkspace();\n const { data: tenantsData, isLoading: isLoadingTenants, error: tenantsError } = useMyTenants();\n const {\n data: organizationsData,\n isLoading: isLoadingOrganizations,\n error: organizationsError,\n } = useMyOrganizations();\n\n const tenants = tenantsData?.items ?? [];\n const allOrganizations = organizationsData?.items ?? [];\n\n const defaultTenantId = useMemo(() => {\n const sharedTenant = tenants.find(\n (tenant) => tenant.type === 'SHARED' || tenant.slug === 'burdenoff-shared'\n );\n return sharedTenant?.id ?? tenants[0]?.id ?? '';\n }, [tenants]);\n\n const form = useForm<CreateWorkspaceFormData>({\n schema: createWorkspaceSchema,\n defaultValues: {\n name: '',\n slug: '',\n tenantId: '',\n organizationId: '',\n type: 'TEAM',\n },\n });\n\n const selectedTenantId = form.watch('tenantId');\n const workspaceName = form.watch('name');\n\n // Filter organizations by selected tenant\n const filteredOrganizations = useMemo(() => {\n if (!selectedTenantId) return [];\n return allOrganizations.filter((org) => org.tenantId === selectedTenantId);\n }, [selectedTenantId, allOrganizations]);\n\n // Auto-generate slug from name (clear when name is empty)\n useEffect(() => {\n form.setValue('slug', workspaceName ? generateSlug(workspaceName) : '');\n }, [workspaceName, form]);\n\n // Reset organizationId when tenant changes\n useEffect(() => {\n form.setValue('organizationId', '');\n }, [selectedTenantId, form]);\n\n useEffect(() => {\n if (!form.getValues('tenantId') && defaultTenantId) {\n form.setValue('tenantId', defaultTenantId, {\n shouldDirty: false,\n shouldTouch: false,\n });\n }\n }, [defaultTenantId, form]);\n\n useEffect(() => {\n const currentOrganizationId = form.getValues('organizationId');\n const hasCurrentOrganization = filteredOrganizations.some(\n (organization) => organization.id === currentOrganizationId\n );\n\n if (!hasCurrentOrganization && filteredOrganizations[0]?.id) {\n form.setValue('organizationId', filteredOrganizations[0].id, {\n shouldDirty: false,\n shouldTouch: false,\n });\n }\n }, [filteredOrganizations, form]);\n\n const onSubmit = (data: CreateWorkspaceFormData) => {\n createWorkspace(\n {\n name: data.name,\n slug: data.slug,\n tenantId: data.tenantId,\n organizationId: data.organizationId,\n type: data.type,\n },\n {\n onSuccess: (newWorkspace) => {\n // Navigate to the new workspace\n navigate(`${basePath}/${newWorkspace.id}`);\n },\n }\n );\n };\n\n return (\n <PermissionGate\n permission={WORKSPACE_PERMISSIONS.WORKSPACE_CREATE}\n fallback={\n <div className=\"p-6\">\n <Link\n to={`${basePath}/list`}\n className=\"inline-flex items-center gap-2 text-muted-foreground hover:text-foreground transition-colors mb-6\"\n >\n <ArrowLeft size={20} />\n {tWithFallback(t, 'createWorkspace.backToWorkspaces', 'Back to Workspaces')}\n </Link>\n <AccessDenied\n variant=\"card\"\n title={tWithFallback(\n t,\n 'createWorkspace.permissionRequiredTitle',\n 'Permission Required'\n )}\n description={tWithFallback(\n t,\n 'createWorkspace.permissionRequiredDescription',\n \"You don't have permission to create workspaces.\"\n )}\n details={tWithFallback(\n t,\n 'createWorkspace.permissionRequiredDetails',\n 'Required: workspace:create'\n )}\n primaryAction={{\n label: tWithFallback(t, 'createWorkspace.goBack', 'Go Back'),\n onClick: () => navigate(`${basePath}/list`),\n }}\n />\n </div>\n }\n >\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n {/* Back link */}\n <Link\n to={`${basePath}/list`}\n className=\"inline-flex items-center gap-2 text-muted-foreground hover:text-foreground transition-colors\"\n >\n <ArrowLeft size={20} />\n {tWithFallback(t, 'createWorkspace.backToWorkspaces', 'Back to Workspaces')}\n </Link>\n\n {/* Form card */}\n <Card className=\"max-w-2xl mx-auto\">\n <CardHeader>\n <CardTitle>\n {tWithFallback(t, 'createWorkspace.title', 'Create New Workspace')}\n </CardTitle>\n <CardDescription>\n {tWithFallback(\n t,\n 'createWorkspace.subtitle',\n 'Set up a new workspace for your team or personal use'\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n <form onSubmit={form.handleSubmit(onSubmit)} className=\"space-y-6\">\n <div className=\"space-y-2\">\n <label htmlFor=\"workspace-name\" className=\"text-sm font-medium text-foreground\">\n {tWithFallback(t, 'createWorkspace.nameLabel', 'Workspace Name *')}\n </label>\n <input\n id=\"workspace-name\"\n placeholder={tWithFallback(t, 'createWorkspace.namePlaceholder', 'My Workspace')}\n className=\"h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground\"\n {...form.register('name')}\n />\n <p className=\"text-xs text-muted-foreground\">\n {tWithFallback(\n t,\n 'createWorkspace.nameHint',\n 'A descriptive name for your workspace'\n )}\n </p>\n {form.formState.errors.name?.message && (\n <p className=\"text-sm text-destructive\">{form.formState.errors.name.message}</p>\n )}\n </div>\n\n <div className=\"space-y-2\">\n <label htmlFor=\"workspace-slug\" className=\"text-sm font-medium text-foreground\">\n {tWithFallback(t, 'createWorkspace.slugLabel', 'Slug *')}\n </label>\n <input\n id=\"workspace-slug\"\n placeholder={tWithFallback(t, 'createWorkspace.slugPlaceholder', 'my-workspace')}\n className=\"h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground\"\n {...form.register('slug')}\n />\n <p className=\"text-xs text-muted-foreground\">\n {tWithFallback(\n t,\n 'createWorkspace.slugHint',\n 'URL-friendly identifier (auto-generated, but you can edit it)'\n )}\n </p>\n {form.formState.errors.slug?.message && (\n <p className=\"text-sm text-destructive\">{form.formState.errors.slug.message}</p>\n )}\n </div>\n\n <div className=\"space-y-2\">\n <label htmlFor=\"workspace-tenant\" className=\"text-sm font-medium text-foreground\">\n {tWithFallback(t, 'createWorkspace.tenantLabel', 'Tenant *')}\n </label>\n {isLoadingTenants ? (\n <Skeleton className=\"h-10 w-full\" />\n ) : tenantsError ? (\n <div className=\"flex items-center gap-2 text-sm text-destructive\">\n <AlertCircle size={16} />\n {tWithFallback(\n t,\n 'createWorkspace.failedToLoadTenants',\n 'Failed to load tenants'\n )}\n </div>\n ) : tenants.length === 0 ? (\n <div className=\"text-sm text-muted-foreground\">\n {tWithFallback(\n t,\n 'createWorkspace.noTenantsAvailable',\n 'No tenants available. Contact your administrator.'\n )}\n </div>\n ) : (\n <select\n id=\"workspace-tenant\"\n className=\"h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground\"\n {...form.register('tenantId')}\n >\n <option value=\"\">\n {tWithFallback(\n t,\n 'createWorkspace.selectTenantPlaceholder',\n 'Select a tenant'\n )}\n </option>\n {tenants.map((tenant) => (\n <option key={tenant.id} value={tenant.id}>\n {tenant.name}\n </option>\n ))}\n </select>\n )}\n <p className=\"text-xs text-muted-foreground\">\n {tWithFallback(\n t,\n 'createWorkspace.tenantHint',\n 'Select which tenant this workspace belongs to'\n )}\n </p>\n {form.formState.errors.tenantId?.message && (\n <p className=\"text-sm text-destructive\">\n {form.formState.errors.tenantId.message}\n </p>\n )}\n </div>\n\n <div className=\"space-y-2\">\n <label\n htmlFor=\"workspace-organization\"\n className=\"text-sm font-medium text-foreground\"\n >\n {tWithFallback(t, 'createWorkspace.organizationLabel', 'Organization *')}\n </label>\n {isLoadingOrganizations ? (\n <Skeleton className=\"h-10 w-full\" />\n ) : organizationsError ? (\n <div className=\"flex items-center gap-2 text-sm text-destructive\">\n <AlertCircle size={16} />\n {tWithFallback(\n t,\n 'createWorkspace.failedToLoadOrganizations',\n 'Failed to load organizations'\n )}\n </div>\n ) : !selectedTenantId ? (\n <div className=\"text-sm text-muted-foreground\">\n {tWithFallback(\n t,\n 'createWorkspace.selectTenantFirst',\n 'Please select a tenant first'\n )}\n </div>\n ) : filteredOrganizations.length === 0 ? (\n <div className=\"text-sm text-muted-foreground\">\n {tWithFallback(\n t,\n 'createWorkspace.noOrganizationsFound',\n 'No organizations found for this tenant'\n )}\n </div>\n ) : (\n <select\n id=\"workspace-organization\"\n className=\"h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground\"\n disabled={!selectedTenantId}\n {...form.register('organizationId')}\n >\n <option value=\"\">\n {tWithFallback(\n t,\n 'createWorkspace.selectOrganizationPlaceholder',\n 'Select an organization'\n )}\n </option>\n {filteredOrganizations.map((org) => (\n <option key={org.id} value={org.id}>\n {org.name}\n </option>\n ))}\n </select>\n )}\n <p className=\"text-xs text-muted-foreground\">\n {tWithFallback(\n t,\n 'createWorkspace.organizationHint',\n 'Select which organization owns this workspace'\n )}\n </p>\n {form.formState.errors.organizationId?.message && (\n <p className=\"text-sm text-destructive\">\n {form.formState.errors.organizationId.message}\n </p>\n )}\n </div>\n\n <div className=\"space-y-2\">\n <label htmlFor=\"workspace-type\" className=\"text-sm font-medium text-foreground\">\n {tWithFallback(t, 'createWorkspace.typeLabel', 'Workspace Type')}\n </label>\n <select\n id=\"workspace-type\"\n className=\"h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground\"\n {...form.register('type')}\n >\n <option value=\"TEAM\">\n {tWithFallback(t, 'createWorkspace.typeTeam', 'Team Workspace')}\n </option>\n <option value=\"PERSONAL\">\n {tWithFallback(t, 'createWorkspace.typePersonal', 'Personal Workspace')}\n </option>\n </select>\n <p className=\"text-xs text-muted-foreground\">\n {tWithFallback(\n t,\n 'createWorkspace.typeHint',\n 'Choose between a collaborative workspace or a personal one'\n )}\n </p>\n </div>\n\n <div className=\"flex justify-end gap-3 pt-4\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => navigate(`${basePath}/list`)}\n disabled={isPending}\n >\n {tWithFallback(t, 'createWorkspace.cancel', 'Cancel')}\n </Button>\n <Button\n type=\"submit\"\n disabled={isPending || isLoadingTenants || isLoadingOrganizations}\n >\n {isPending\n ? tWithFallback(t, 'createWorkspace.creating', 'Creating...')\n : tWithFallback(t, 'createWorkspace.submit', 'Create Workspace')}\n </Button>\n </div>\n </form>\n </CardContent>\n </Card>\n </div>\n </PermissionGate>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CreateWorkspacePage.js","names":[],"sources":["../../src/pages/CreateWorkspacePage.tsx"],"sourcesContent":["import { useEffect, useMemo } from 'react';\nimport { ArrowLeft, AlertCircle } from 'lucide-react';\nimport { Link, useNavigate } from 'react-router-dom';\nimport {\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n Skeleton,\n} from '@burdenoff/fe-libs/ui';\nimport { useForm, z } from '@burdenoff/fe-libs/form';\nimport { AccessDenied, UpgradeInlineBanner } from '@burdenoff/fe-libs/shared/components';\nimport { useUpgradePrompt } from '@burdenoff/fe-libs/shared/hooks';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useCreateWorkspace } from '../hooks/useWorkspaceMutations';\nimport { useMyTenants, useMyOrganizations } from '../hooks/useTenants';\nimport { useOrgsWithPermission } from '../hooks/useOrgsWithPermission';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport { useWorkspacesPageView } from '../hooks/useWorkspacesPageView';\nimport { generateSlug } from '../utils/slug';\nimport { tWithFallback } from '../utils/i18n';\n\ntype CreateWorkspaceFormData = {\n name: string;\n slug: string;\n tenantId: string;\n organizationId: string;\n type?: 'TEAM' | 'PERSONAL';\n};\n\nexport function CreateWorkspacePage() {\n useWorkspacesPageView('workspaces.create');\n const { t } = useI18n();\n const {\n isFree,\n approachingLimits,\n plan: planSnapshot,\n } = useUpgradePrompt({ resource: 'workspaces' });\n const workspacesUsage = approachingLimits[0];\n const atWorkspaceCap =\n !!workspacesUsage &&\n typeof workspacesUsage.limit === 'number' &&\n workspacesUsage.current >= workspacesUsage.limit;\n const showUpgradeBanner = isFree && !!workspacesUsage;\n const createWorkspaceSchema = useMemo(\n () =>\n z.object({\n name: z\n .string()\n .min(\n 2,\n tWithFallback(\n t,\n 'createWorkspace.validation.nameMin',\n 'Name must be at least 2 characters'\n )\n )\n .max(100),\n slug: z\n .string()\n .min(\n 2,\n tWithFallback(\n t,\n 'createWorkspace.validation.slugMin',\n 'Slug must be at least 2 characters'\n )\n )\n .max(50)\n .regex(\n /^[a-z0-9-]+$/,\n tWithFallback(\n t,\n 'createWorkspace.validation.slugFormat',\n 'Slug can only contain lowercase letters, numbers, and hyphens'\n )\n ),\n tenantId: z\n .string()\n .min(\n 1,\n tWithFallback(t, 'createWorkspace.validation.tenantRequired', 'Please select a tenant')\n ),\n organizationId: z\n .string()\n .min(\n 1,\n tWithFallback(\n t,\n 'createWorkspace.validation.organizationRequired',\n 'Please select an organization'\n )\n ),\n type: z.enum(['TEAM', 'PERSONAL']).optional(),\n }),\n [t]\n );\n\n const navigate = useNavigate();\n const { basePath = '/' } = useWorkspacesContext();\n const { mutate: createWorkspace, isPending } = useCreateWorkspace();\n const { data: tenantsData, isLoading: isLoadingTenants, error: tenantsError } = useMyTenants();\n const {\n data: organizationsData,\n isLoading: isLoadingOrganizations,\n error: organizationsError,\n } = useMyOrganizations();\n\n const tenants = useMemo(() => tenantsData?.items ?? [], [tenantsData]);\n const allOrganizations = useMemo(() => organizationsData?.items ?? [], [organizationsData]);\n\n const defaultTenantId = useMemo(() => {\n const sharedTenant = tenants.find(\n (tenant) => tenant.type === 'SHARED' || tenant.slug === 'burdenoff-shared'\n );\n return sharedTenant?.id ?? tenants[0]?.id ?? '';\n }, [tenants]);\n\n const form = useForm<CreateWorkspaceFormData>({\n schema: createWorkspaceSchema,\n defaultValues: {\n name: '',\n slug: '',\n tenantId: '',\n organizationId: '',\n type: 'TEAM',\n },\n });\n\n const selectedTenantId = form.watch('tenantId');\n const workspaceName = form.watch('name');\n\n // Check workspace:create permission across ALL the user's orgs up front\n // (bulk-checked in a single rbac round-trip). This is the authoritative\n // gate — only orgs where the user can actually create a workspace make\n // it into the dropdown, and the page can decisively render the \"no\n // permissions anywhere\" state once the check resolves.\n const allOrgIds = useMemo(() => allOrganizations.map((o) => o.id), [allOrganizations]);\n const {\n allowedIds: workspaceCreateAllowedOrgIds,\n loading: isCheckingOrgPermissions,\n isError: orgPermissionsHadError,\n } = useOrgsWithPermission(allOrgIds, 'workspace', 'create');\n\n // Filter organizations by selected tenant AND permission. When the rbac\n // permission lookup errored we deliberately skip the permission filter\n // (see `orgPermissionsHadError` block below) — the gateway @rbac\n // directive on `createWorkspace` is the authoritative gate, so it's\n // safer to let the user pick from the full tenant list and hit a 403 on\n // submit than to lock them out of a flow they actually have access to.\n const tenantOrganizations = useMemo(() => {\n if (!selectedTenantId) return [];\n return allOrganizations.filter((org) => org.tenantId === selectedTenantId);\n }, [selectedTenantId, allOrganizations]);\n const filteredOrganizations = useMemo(() => {\n if (orgPermissionsHadError) return tenantOrganizations;\n return tenantOrganizations.filter((org) => workspaceCreateAllowedOrgIds.has(org.id));\n }, [tenantOrganizations, workspaceCreateAllowedOrgIds, orgPermissionsHadError]);\n\n // Auto-generate slug from name (clear when name is empty)\n useEffect(() => {\n form.setValue('slug', workspaceName ? generateSlug(workspaceName) : '');\n }, [workspaceName, form]);\n\n // Reset organizationId when tenant changes\n useEffect(() => {\n form.setValue('organizationId', '');\n }, [selectedTenantId, form]);\n\n useEffect(() => {\n if (!form.getValues('tenantId') && defaultTenantId) {\n form.setValue('tenantId', defaultTenantId, {\n shouldDirty: false,\n shouldTouch: false,\n });\n }\n }, [defaultTenantId, form]);\n\n useEffect(() => {\n const currentOrganizationId = form.getValues('organizationId');\n const hasCurrentOrganization = filteredOrganizations.some(\n (organization) => organization.id === currentOrganizationId\n );\n\n if (!hasCurrentOrganization && filteredOrganizations[0]?.id) {\n form.setValue('organizationId', filteredOrganizations[0].id, {\n shouldDirty: false,\n shouldTouch: false,\n });\n }\n }, [filteredOrganizations, form]);\n\n const onSubmit = (data: CreateWorkspaceFormData) => {\n createWorkspace(\n {\n name: data.name,\n slug: data.slug,\n tenantId: data.tenantId,\n organizationId: data.organizationId,\n type: data.type,\n },\n {\n onSuccess: (newWorkspace) => {\n // Navigate to the new workspace\n navigate(`${basePath}/${newWorkspace.id}`);\n },\n }\n );\n };\n\n // `workspace:create` is an org-scoped permission. Page-level `PermissionGate`\n // resolved at the outer shell scope and incorrectly denied users who *do*\n // have the permission inside at least one of their orgs. The authoritative\n // gate now lives on the org dropdown (only orgs where the user has\n // workspace:create are listed via useOrgsWithPermission) and on the gateway\n // @rbac directive enforcing the createWorkspace mutation. We still want a\n // clear \"you can't create anywhere\" empty state — once tenants and org\n // permission lookups have settled, if no org is eligible we render it.\n // The AccessDenied empty-state should ONLY render when we know with\n // certainty that the user has no creatable org. That requires:\n // 1. tenants + organizations queries both succeeded (otherwise an\n // empty `allOrganizations` is a data-fetch failure, not an authz\n // failure — masking it as \"permission denied\" hides the real\n // error and offers the user no path to retry),\n // 2. the rbac permission lookup also succeeded (errors there fall\n // through to the unfiltered form via the warning banner below),\n // 3. and even then, only when the user has at least one org but none\n // of them allow workspace:create.\n // If `allOrganizations` is empty because the user genuinely belongs to\n // no orgs, the inner \"no organizations found for this tenant\" message\n // is a better surface than an authz-denied page.\n const hasAnyCreatableOrg = workspaceCreateAllowedOrgIds.size > 0;\n const stillResolvingPermissions =\n isLoadingTenants || isLoadingOrganizations || isCheckingOrgPermissions;\n const orgDataLoadedSuccessfully =\n !tenantsError && !organizationsError && allOrganizations.length > 0;\n if (\n !stillResolvingPermissions &&\n !orgPermissionsHadError &&\n orgDataLoadedSuccessfully &&\n !hasAnyCreatableOrg\n ) {\n return (\n <div className=\"p-6\">\n <Link\n to={`${basePath}/list`}\n className=\"inline-flex items-center gap-2 text-muted-foreground hover:text-foreground transition-colors mb-6\"\n >\n <ArrowLeft size={20} />\n {tWithFallback(t, 'createWorkspace.backToWorkspaces', 'Back to Workspaces')}\n </Link>\n <AccessDenied\n variant=\"card\"\n title={tWithFallback(t, 'createWorkspace.permissionRequiredTitle', 'Permission Required')}\n description={tWithFallback(\n t,\n 'createWorkspace.permissionRequiredDescription',\n \"You don't have permission to create workspaces in any of your organizations.\"\n )}\n details={tWithFallback(\n t,\n 'createWorkspace.permissionRequiredDetails',\n 'Required: workspace:create'\n )}\n primaryAction={{\n label: tWithFallback(t, 'createWorkspace.goBack', 'Go Back'),\n onClick: () => navigate(`${basePath}/list`),\n }}\n />\n </div>\n );\n }\n\n return (\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n {/* Back link */}\n <Link\n to={`${basePath}/list`}\n className=\"inline-flex items-center gap-2 text-muted-foreground hover:text-foreground transition-colors\"\n >\n <ArrowLeft size={20} />\n {tWithFallback(t, 'createWorkspace.backToWorkspaces', 'Back to Workspaces')}\n </Link>\n\n {showUpgradeBanner && (\n <div className=\"max-w-2xl mx-auto w-full\">\n <UpgradeInlineBanner\n resource=\"workspaces\"\n current={workspacesUsage.current}\n limit={workspacesUsage.limit ?? undefined}\n severity={atWorkspaceCap ? 'critical' : undefined}\n message={\n atWorkspaceCap\n ? tWithFallback(\n t,\n 'createWorkspace.upgradeCapMessage',\n `You've used all workspaces in the ${planSnapshot?.planName ?? 'free'} plan.`\n )\n : tWithFallback(\n t,\n 'createWorkspace.upgradeApproachingMessage',\n 'Upgrade to create more workspaces.'\n )\n }\n />\n </div>\n )}\n\n {/* Form card */}\n <Card className=\"max-w-2xl mx-auto\">\n <CardHeader>\n <CardTitle>{tWithFallback(t, 'createWorkspace.title', 'Create New Workspace')}</CardTitle>\n <CardDescription>\n {tWithFallback(\n t,\n 'createWorkspace.subtitle',\n 'Set up a new workspace for your team or personal use'\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n {orgPermissionsHadError && (\n <div\n role=\"alert\"\n className=\"mb-4 flex items-start gap-2 rounded-md border border-warning/30 bg-warning/10 p-3 text-sm text-foreground\"\n >\n <AlertCircle size={16} className=\"mt-0.5 shrink-0 text-warning\" />\n <span>\n {tWithFallback(\n t,\n 'createWorkspace.permissionCheckUnavailable',\n \"We couldn't verify your workspace-create permissions just now, so the organization list isn't filtered. If you submit and don't have access, the request will be rejected and you can retry.\"\n )}\n </span>\n </div>\n )}\n <form onSubmit={form.handleSubmit(onSubmit)} className=\"space-y-6\">\n <div className=\"space-y-2\">\n <label htmlFor=\"workspace-name\" className=\"text-sm font-medium text-foreground\">\n {tWithFallback(t, 'createWorkspace.nameLabel', 'Workspace Name *')}\n </label>\n <input\n id=\"workspace-name\"\n placeholder={tWithFallback(t, 'createWorkspace.namePlaceholder', 'My Workspace')}\n className=\"h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground\"\n {...form.register('name')}\n />\n <p className=\"text-xs text-muted-foreground\">\n {tWithFallback(\n t,\n 'createWorkspace.nameHint',\n 'A descriptive name for your workspace'\n )}\n </p>\n {form.formState.errors.name?.message && (\n <p className=\"text-sm text-destructive\">{form.formState.errors.name.message}</p>\n )}\n </div>\n\n <div className=\"space-y-2\">\n <label htmlFor=\"workspace-slug\" className=\"text-sm font-medium text-foreground\">\n {tWithFallback(t, 'createWorkspace.slugLabel', 'Slug *')}\n </label>\n <input\n id=\"workspace-slug\"\n placeholder={tWithFallback(t, 'createWorkspace.slugPlaceholder', 'my-workspace')}\n className=\"h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground\"\n {...form.register('slug')}\n />\n <p className=\"text-xs text-muted-foreground\">\n {tWithFallback(\n t,\n 'createWorkspace.slugHint',\n 'URL-friendly identifier (auto-generated, but you can edit it)'\n )}\n </p>\n {form.formState.errors.slug?.message && (\n <p className=\"text-sm text-destructive\">{form.formState.errors.slug.message}</p>\n )}\n </div>\n\n <div className=\"space-y-2\">\n <label htmlFor=\"workspace-tenant\" className=\"text-sm font-medium text-foreground\">\n {tWithFallback(t, 'createWorkspace.tenantLabel', 'Tenant *')}\n </label>\n {isLoadingTenants ? (\n <Skeleton className=\"h-10 w-full\" />\n ) : tenantsError ? (\n <div className=\"flex items-center gap-2 text-sm text-destructive\">\n <AlertCircle size={16} />\n {tWithFallback(\n t,\n 'createWorkspace.failedToLoadTenants',\n 'Failed to load tenants'\n )}\n </div>\n ) : tenants.length === 0 ? (\n <div className=\"text-sm text-muted-foreground\">\n {tWithFallback(\n t,\n 'createWorkspace.noTenantsAvailable',\n 'No tenants available. Contact your administrator.'\n )}\n </div>\n ) : (\n <select\n id=\"workspace-tenant\"\n className=\"h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground\"\n {...form.register('tenantId')}\n >\n <option value=\"\">\n {tWithFallback(t, 'createWorkspace.selectTenantPlaceholder', 'Select a tenant')}\n </option>\n {tenants.map((tenant) => (\n <option key={tenant.id} value={tenant.id}>\n {tenant.name}\n </option>\n ))}\n </select>\n )}\n <p className=\"text-xs text-muted-foreground\">\n {tWithFallback(\n t,\n 'createWorkspace.tenantHint',\n 'Select which tenant this workspace belongs to'\n )}\n </p>\n {form.formState.errors.tenantId?.message && (\n <p className=\"text-sm text-destructive\">{form.formState.errors.tenantId.message}</p>\n )}\n </div>\n\n <div className=\"space-y-2\">\n <label\n htmlFor=\"workspace-organization\"\n className=\"text-sm font-medium text-foreground\"\n >\n {tWithFallback(t, 'createWorkspace.organizationLabel', 'Organization *')}\n </label>\n {isLoadingOrganizations || isCheckingOrgPermissions ? (\n // While the permission check is in flight,\n // `workspaceCreateAllowedOrgIds` is empty so\n // `filteredOrganizations` is also empty. Render the same\n // skeleton we use for the org-load itself instead of the\n // \"no organizations found\" empty-state — otherwise a slow\n // rbac response briefly looks like an authorization\n // failure for users who DO have workspace:create.\n <Skeleton className=\"h-10 w-full\" />\n ) : organizationsError ? (\n <div className=\"flex items-center gap-2 text-sm text-destructive\">\n <AlertCircle size={16} />\n {tWithFallback(\n t,\n 'createWorkspace.failedToLoadOrganizations',\n 'Failed to load organizations'\n )}\n </div>\n ) : !selectedTenantId ? (\n <div className=\"text-sm text-muted-foreground\">\n {tWithFallback(\n t,\n 'createWorkspace.selectTenantFirst',\n 'Please select a tenant first'\n )}\n </div>\n ) : filteredOrganizations.length === 0 ? (\n <div className=\"text-sm text-muted-foreground\">\n {tWithFallback(\n t,\n 'createWorkspace.noOrganizationsFound',\n 'No organizations found for this tenant'\n )}\n </div>\n ) : (\n <select\n id=\"workspace-organization\"\n className=\"h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground\"\n disabled={!selectedTenantId}\n {...form.register('organizationId')}\n >\n <option value=\"\">\n {tWithFallback(\n t,\n 'createWorkspace.selectOrganizationPlaceholder',\n 'Select an organization'\n )}\n </option>\n {filteredOrganizations.map((org) => (\n <option key={org.id} value={org.id}>\n {org.name}\n </option>\n ))}\n </select>\n )}\n <p className=\"text-xs text-muted-foreground\">\n {tWithFallback(\n t,\n 'createWorkspace.organizationHint',\n 'Select which organization owns this workspace'\n )}\n </p>\n {form.formState.errors.organizationId?.message && (\n <p className=\"text-sm text-destructive\">\n {form.formState.errors.organizationId.message}\n </p>\n )}\n </div>\n\n <div className=\"space-y-2\">\n <label htmlFor=\"workspace-type\" className=\"text-sm font-medium text-foreground\">\n {tWithFallback(t, 'createWorkspace.typeLabel', 'Workspace Type')}\n </label>\n <select\n id=\"workspace-type\"\n className=\"h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground\"\n {...form.register('type')}\n >\n <option value=\"TEAM\">\n {tWithFallback(t, 'createWorkspace.typeTeam', 'Team Workspace')}\n </option>\n <option value=\"PERSONAL\">\n {tWithFallback(t, 'createWorkspace.typePersonal', 'Personal Workspace')}\n </option>\n </select>\n <p className=\"text-xs text-muted-foreground\">\n {tWithFallback(\n t,\n 'createWorkspace.typeHint',\n 'Choose between a collaborative workspace or a personal one'\n )}\n </p>\n </div>\n\n <div className=\"flex justify-end gap-3 pt-4\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => navigate(`${basePath}/list`)}\n disabled={isPending}\n >\n {tWithFallback(t, 'createWorkspace.cancel', 'Cancel')}\n </Button>\n <Button\n type=\"submit\"\n disabled={\n isPending ||\n isLoadingTenants ||\n isLoadingOrganizations ||\n isCheckingOrgPermissions ||\n atWorkspaceCap\n }\n title={\n atWorkspaceCap\n ? tWithFallback(\n t,\n 'createWorkspace.disabledAtCap',\n 'Workspace limit reached — upgrade your plan to create more.'\n )\n : undefined\n }\n >\n {isPending\n ? tWithFallback(t, 'createWorkspace.creating', 'Creating...')\n : tWithFallback(t, 'createWorkspace.submit', 'Create Workspace')}\n </Button>\n </div>\n </form>\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
|