@burdenoff/microfe-organization 2026.601.8 → 2026.616.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. package/dist/generated/global-operations.js +78 -63
  2. package/dist/generated/global-operations.js.map +1 -1
  3. package/dist/generated/global-types.js.map +1 -1
  4. package/dist/organization-management/UserOrganizationRoutes.js +13 -9
  5. package/dist/organization-management/UserOrganizationRoutes.js.map +1 -1
  6. package/dist/organization-management/modules/members/hooks/useInvites.js +79 -65
  7. package/dist/organization-management/modules/members/hooks/useInvites.js.map +1 -1
  8. package/dist/organization-management/modules/members/pages/OrganizationInviteAcceptancePage.js +287 -0
  9. package/dist/organization-management/modules/members/pages/OrganizationInviteAcceptancePage.js.map +1 -0
  10. package/dist/organization-management/modules/organizations/components/OrganizationForm.js +112 -112
  11. package/dist/organization-management/modules/organizations/components/OrganizationForm.js.map +1 -1
  12. package/dist/organization-management/modules/organizations/pages/OrganizationCreatePage.js +8 -7
  13. package/dist/organization-management/modules/organizations/pages/OrganizationCreatePage.js.map +1 -1
  14. package/dist/organization-management/modules/workspaces/components/WorkspaceCard.js +2 -5
  15. package/dist/organization-management/modules/workspaces/components/WorkspaceCard.js.map +1 -1
  16. package/dist/organization-management/modules/workspaces/components/WorkspaceForm.js +86 -134
  17. package/dist/organization-management/modules/workspaces/components/WorkspaceForm.js.map +1 -1
  18. package/dist/organization-management/modules/workspaces/hooks/useWorkspaces.js.map +1 -1
  19. package/dist/organization-management/modules/workspaces/pages/WorkspaceDetailPage.js +4 -18
  20. package/dist/organization-management/modules/workspaces/pages/WorkspaceDetailPage.js.map +1 -1
  21. package/dist/organization-management/modules/workspaces/pages/WorkspacesListPage.js +4 -22
  22. package/dist/organization-management/modules/workspaces/pages/WorkspacesListPage.js.map +1 -1
  23. package/package.json +1 -1
@@ -54,12 +54,9 @@ function o({ workspace: o, onClick: s, onEdit: c, onDelete: l, showActions: u =
54
54
  children: /* @__PURE__ */ i(r, { size: 18 })
55
55
  })]
56
56
  }),
57
- /* @__PURE__ */ a("div", {
57
+ /* @__PURE__ */ i("div", {
58
58
  className: "flex gap-2 mb-4",
59
- children: [/* @__PURE__ */ i(t, { status: o.status }), /* @__PURE__ */ i("span", {
60
- className: "inline-flex items-center px-2 py-1 rounded-md text-xs font-medium bg-[var(--color-bg-subtle)] text-[var(--color-text-secondary)]",
61
- children: o.type
62
- })]
59
+ children: /* @__PURE__ */ i(t, { status: o.status })
63
60
  }),
64
61
  o.memberCount !== void 0 && /* @__PURE__ */ a("p", {
65
62
  className: "text-sm text-[var(--color-text-secondary)] mb-4",
@@ -1 +1 @@
1
- {"version":3,"file":"WorkspaceCard.js","names":[],"sources":["../../../../../src/organization-management/modules/workspaces/components/WorkspaceCard.tsx"],"sourcesContent":["import { Briefcase, MoreVertical } from 'lucide-react';\nimport { WorkspaceStatusBadge } from './WorkspaceStatusBadge';\nimport type { Workspace } from '../types';\nimport { useTr } from '../../../shared/hooks/useTr';\n\ninterface WorkspaceCardProps {\n workspace: Workspace;\n onClick?: (workspace: Workspace) => void;\n onEdit?: (workspace: Workspace) => void;\n onDelete?: (workspace: Workspace) => void;\n showActions?: boolean;\n}\n\n/**\n * WorkspaceCard\n * Displays a workspace in a card format for grid views\n */\nexport function WorkspaceCard({\n workspace,\n onClick,\n onEdit,\n onDelete,\n showActions = true,\n}: WorkspaceCardProps) {\n const tr = useTr();\n const handleCardClick = () => {\n if (onClick) {\n onClick(workspace);\n }\n };\n\n const handleEdit = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (onEdit) {\n onEdit(workspace);\n }\n };\n\n const handleDelete = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (onDelete) {\n onDelete(workspace);\n }\n };\n\n return (\n // react-doctor-disable-next-line react-doctor/no-static-element-interactions\n <div\n onClick={onClick ? handleCardClick : undefined}\n onKeyDown={\n onClick\n ? (event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n handleCardClick();\n }\n }\n : undefined\n }\n className={`\n w-full text-left\n bg-[var(--color-bg-surface)]\n border border-[var(--color-border-default)]\n rounded-lg\n p-6\n shadow-[var(--shadow-elevation-1)]\n transition-all\n ${onClick ? 'cursor-pointer hover:shadow-[var(--shadow-elevation-2)] hover:border-[var(--color-border-hover)]' : ''}\n `}\n aria-label={\n onClick ? `${tr('workspaces.card.open', 'Open workspace')} ${workspace.name}` : undefined\n }\n role={onClick ? 'button' : undefined}\n tabIndex={onClick ? 0 : undefined}\n >\n {/* Header */}\n <div className=\"flex items-start justify-between mb-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"size-12 rounded-lg bg-[var(--color-status-info-muted)] flex items-center justify-center\">\n <Briefcase size={24} className=\"text-[var(--color-status-info)]\" />\n </div>\n <div className=\"flex-1\">\n <h3 className=\"font-semibold text-[var(--color-text-primary)] text-lg\">\n {workspace.name}\n </h3>\n <p className=\"text-sm text-[var(--color-text-muted)] font-mono\">/{workspace.slug}</p>\n </div>\n </div>\n\n {showActions && (\n <button\n type=\"button\"\n onClick={(e) => e.stopPropagation()}\n className=\"\n p-1.5 rounded-lg\n text-[var(--color-text-secondary)]\n hover:bg-[var(--color-bg-subtle)]\n active:scale-95\n transition-all duration-200\n \"\n aria-label={`${tr('workspaces.card.actionsFor', 'Workspace actions for')} ${workspace.name}`}\n >\n <MoreVertical size={18} />\n </button>\n )}\n </div>\n\n {/* Badges */}\n <div className=\"flex gap-2 mb-4\">\n <WorkspaceStatusBadge status={workspace.status} />\n <span className=\"inline-flex items-center px-2 py-1 rounded-md text-xs font-medium bg-[var(--color-bg-subtle)] text-[var(--color-text-secondary)]\">\n {workspace.type}\n </span>\n </div>\n\n {/* Member Count */}\n {workspace.memberCount !== undefined && (\n <p className=\"text-sm text-[var(--color-text-secondary)] mb-4\">\n {workspace.memberCount}{' '}\n {workspace.memberCount === 1\n ? tr('members.role.member', 'Member').toLowerCase()\n : tr('workspaces.list.members', 'Members').toLowerCase()}\n </p>\n )}\n\n {/* Metadata */}\n <div className=\"pt-2 border-t border-[var(--color-border-default)]\">\n <p className=\"text-xs text-[var(--color-text-muted)]\">\n {tr('common.created', 'Created')} {new Date(workspace.createdAt).toLocaleDateString()}\n </p>\n </div>\n\n {/* Footer Actions */}\n {showActions && (onEdit || onDelete) && (\n <div className=\"flex gap-2 mt-4 pt-4 border-t border-[var(--color-border-default)]\">\n {onEdit && (\n <button\n type=\"button\"\n onClick={handleEdit}\n className=\"\n flex-1 px-3 py-1.5 text-sm\n bg-[var(--color-bg-subtle)]\n text-[var(--color-text-primary)]\n rounded-lg\n hover:bg-[var(--color-bg-muted)]\n active:scale-[0.98]\n transition-all duration-200\n font-medium\n \"\n >\n {tr('common.edit', 'Edit')}\n </button>\n )}\n {onDelete && (\n <button\n type=\"button\"\n onClick={handleDelete}\n className=\"\n flex-1 px-3 py-1.5 text-sm\n bg-[var(--color-status-error-muted)]\n text-[var(--color-status-error)]\n rounded-lg\n hover:opacity-80\n active:scale-[0.98]\n transition-all duration-200\n font-medium\n \"\n >\n {tr('common.delete', 'Delete')}\n </button>\n )}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;AAiBA,SAAgB,EAAc,EAC5B,cACA,YACA,WACA,aACA,iBAAc,MACO;CACrB,IAAM,IAAK,GAAO,EACZ,UAAwB;AAC5B,EAAI,KACF,EAAQ,EAAU;;AAkBtB,QAEE,kBAAC,OAAD;EACE,SAAS,IAAU,IAAkB,KAAA;EACrC,WACE,KACK,MAAU;AACT,IAAI,EAAM,QAAQ,WAAW,EAAM,QAAQ,SACzC,EAAM,gBAAgB,EACtB,GAAiB;MAGrB,KAAA;EAEN,WAAW;;;;;;;;UAQP,IAAU,qGAAqG,GAAG;;EAEtH,cACE,IAAU,GAAG,EAAG,wBAAwB,iBAAiB,CAAC,GAAG,EAAU,SAAS,KAAA;EAElF,MAAM,IAAU,WAAW,KAAA;EAC3B,UAAU,IAAU,IAAI,KAAA;YA1B1B;GA6BE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD;OAAW,MAAM;OAAI,WAAU;OAAoC,CAAA;MAC/D,CAAA,EACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAU;OACR,CAAA,EACL,kBAAC,KAAD;OAAG,WAAU;iBAAb,CAAgE,KAAE,EAAU,KAAS;SACjF;QACF;QAEL,KACC,kBAAC,UAAD;KACE,MAAK;KACL,UAAU,MAAM,EAAE,iBAAiB;KACnC,WAAU;KAOV,cAAY,GAAG,EAAG,8BAA8B,wBAAwB,CAAC,GAAG,EAAU;eAEtF,kBAAC,GAAD,EAAc,MAAM,IAAM,CAAA;KACnB,CAAA,CAEP;;GAGN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD,EAAsB,QAAQ,EAAU,QAAU,CAAA,EAClD,kBAAC,QAAD;KAAM,WAAU;eACb,EAAU;KACN,CAAA,CACH;;GAGL,EAAU,gBAAgB,KAAA,KACzB,kBAAC,KAAD;IAAG,WAAU;cAAb;KACG,EAAU;KAAa;KACvB,EAAU,gBAAgB,IACvB,EAAG,uBAAuB,SAAS,CAAC,aAAa,GACjD,EAAG,2BAA2B,UAAU,CAAC,aAAa;KACxD;;GAIN,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,KAAD;KAAG,WAAU;eAAb;MACG,EAAG,kBAAkB,UAAU;MAAC;MAAE,IAAI,KAAK,EAAU,UAAU,CAAC,oBAAoB;MACnF;;IACA,CAAA;GAGL,MAAgB,KAAU,MACzB,kBAAC,OAAD;IAAK,WAAU;cAAf,CACG,KACC,kBAAC,UAAD;KACE,MAAK;KACL,UA3GQ,MAAwB;AAE1C,MADA,EAAE,iBAAiB,EACf,KACF,EAAO,EAAU;;KAyGT,WAAU;eAWT,EAAG,eAAe,OAAO;KACnB,CAAA,EAEV,KACC,kBAAC,UAAD;KACE,MAAK;KACL,UAtHU,MAAwB;AAE5C,MADA,EAAE,iBAAiB,EACf,KACF,EAAS,EAAU;;KAoHX,WAAU;eAWT,EAAG,iBAAiB,SAAS;KACvB,CAAA,CAEP;;GAEJ"}
1
+ {"version":3,"file":"WorkspaceCard.js","names":[],"sources":["../../../../../src/organization-management/modules/workspaces/components/WorkspaceCard.tsx"],"sourcesContent":["import { Briefcase, MoreVertical } from 'lucide-react';\nimport { WorkspaceStatusBadge } from './WorkspaceStatusBadge';\nimport type { Workspace } from '../types';\nimport { useTr } from '../../../shared/hooks/useTr';\n\ninterface WorkspaceCardProps {\n workspace: Workspace;\n onClick?: (workspace: Workspace) => void;\n onEdit?: (workspace: Workspace) => void;\n onDelete?: (workspace: Workspace) => void;\n showActions?: boolean;\n}\n\n/**\n * WorkspaceCard\n * Displays a workspace in a card format for grid views\n */\nexport function WorkspaceCard({\n workspace,\n onClick,\n onEdit,\n onDelete,\n showActions = true,\n}: WorkspaceCardProps) {\n const tr = useTr();\n const handleCardClick = () => {\n if (onClick) {\n onClick(workspace);\n }\n };\n\n const handleEdit = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (onEdit) {\n onEdit(workspace);\n }\n };\n\n const handleDelete = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (onDelete) {\n onDelete(workspace);\n }\n };\n\n return (\n // react-doctor-disable-next-line react-doctor/no-static-element-interactions\n <div\n onClick={onClick ? handleCardClick : undefined}\n onKeyDown={\n onClick\n ? (event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n handleCardClick();\n }\n }\n : undefined\n }\n className={`\n w-full text-left\n bg-[var(--color-bg-surface)]\n border border-[var(--color-border-default)]\n rounded-lg\n p-6\n shadow-[var(--shadow-elevation-1)]\n transition-all\n ${onClick ? 'cursor-pointer hover:shadow-[var(--shadow-elevation-2)] hover:border-[var(--color-border-hover)]' : ''}\n `}\n aria-label={\n onClick ? `${tr('workspaces.card.open', 'Open workspace')} ${workspace.name}` : undefined\n }\n role={onClick ? 'button' : undefined}\n tabIndex={onClick ? 0 : undefined}\n >\n {/* Header */}\n <div className=\"flex items-start justify-between mb-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"size-12 rounded-lg bg-[var(--color-status-info-muted)] flex items-center justify-center\">\n <Briefcase size={24} className=\"text-[var(--color-status-info)]\" />\n </div>\n <div className=\"flex-1\">\n <h3 className=\"font-semibold text-[var(--color-text-primary)] text-lg\">\n {workspace.name}\n </h3>\n <p className=\"text-sm text-[var(--color-text-muted)] font-mono\">/{workspace.slug}</p>\n </div>\n </div>\n\n {showActions && (\n <button\n type=\"button\"\n onClick={(e) => e.stopPropagation()}\n className=\"\n p-1.5 rounded-lg\n text-[var(--color-text-secondary)]\n hover:bg-[var(--color-bg-subtle)]\n active:scale-95\n transition-all duration-200\n \"\n aria-label={`${tr('workspaces.card.actionsFor', 'Workspace actions for')} ${workspace.name}`}\n >\n <MoreVertical size={18} />\n </button>\n )}\n </div>\n\n {/* Badges */}\n <div className=\"flex gap-2 mb-4\">\n <WorkspaceStatusBadge status={workspace.status} />\n </div>\n\n {/* Member Count */}\n {workspace.memberCount !== undefined && (\n <p className=\"text-sm text-[var(--color-text-secondary)] mb-4\">\n {workspace.memberCount}{' '}\n {workspace.memberCount === 1\n ? tr('members.role.member', 'Member').toLowerCase()\n : tr('workspaces.list.members', 'Members').toLowerCase()}\n </p>\n )}\n\n {/* Metadata */}\n <div className=\"pt-2 border-t border-[var(--color-border-default)]\">\n <p className=\"text-xs text-[var(--color-text-muted)]\">\n {tr('common.created', 'Created')} {new Date(workspace.createdAt).toLocaleDateString()}\n </p>\n </div>\n\n {/* Footer Actions */}\n {showActions && (onEdit || onDelete) && (\n <div className=\"flex gap-2 mt-4 pt-4 border-t border-[var(--color-border-default)]\">\n {onEdit && (\n <button\n type=\"button\"\n onClick={handleEdit}\n className=\"\n flex-1 px-3 py-1.5 text-sm\n bg-[var(--color-bg-subtle)]\n text-[var(--color-text-primary)]\n rounded-lg\n hover:bg-[var(--color-bg-muted)]\n active:scale-[0.98]\n transition-all duration-200\n font-medium\n \"\n >\n {tr('common.edit', 'Edit')}\n </button>\n )}\n {onDelete && (\n <button\n type=\"button\"\n onClick={handleDelete}\n className=\"\n flex-1 px-3 py-1.5 text-sm\n bg-[var(--color-status-error-muted)]\n text-[var(--color-status-error)]\n rounded-lg\n hover:opacity-80\n active:scale-[0.98]\n transition-all duration-200\n font-medium\n \"\n >\n {tr('common.delete', 'Delete')}\n </button>\n )}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;AAiBA,SAAgB,EAAc,EAC5B,cACA,YACA,WACA,aACA,iBAAc,MACO;CACrB,IAAM,IAAK,GAAO,EACZ,UAAwB;AAC5B,EAAI,KACF,EAAQ,EAAU;;AAkBtB,QAEE,kBAAC,OAAD;EACE,SAAS,IAAU,IAAkB,KAAA;EACrC,WACE,KACK,MAAU;AACT,IAAI,EAAM,QAAQ,WAAW,EAAM,QAAQ,SACzC,EAAM,gBAAgB,EACtB,GAAiB;MAGrB,KAAA;EAEN,WAAW;;;;;;;;UAQP,IAAU,qGAAqG,GAAG;;EAEtH,cACE,IAAU,GAAG,EAAG,wBAAwB,iBAAiB,CAAC,GAAG,EAAU,SAAS,KAAA;EAElF,MAAM,IAAU,WAAW,KAAA;EAC3B,UAAU,IAAU,IAAI,KAAA;YA1B1B;GA6BE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD;OAAW,MAAM;OAAI,WAAU;OAAoC,CAAA;MAC/D,CAAA,EACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAU;OACR,CAAA,EACL,kBAAC,KAAD;OAAG,WAAU;iBAAb,CAAgE,KAAE,EAAU,KAAS;SACjF;QACF;QAEL,KACC,kBAAC,UAAD;KACE,MAAK;KACL,UAAU,MAAM,EAAE,iBAAiB;KACnC,WAAU;KAOV,cAAY,GAAG,EAAG,8BAA8B,wBAAwB,CAAC,GAAG,EAAU;eAEtF,kBAAC,GAAD,EAAc,MAAM,IAAM,CAAA;KACnB,CAAA,CAEP;;GAGN,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD,EAAsB,QAAQ,EAAU,QAAU,CAAA;IAC9C,CAAA;GAGL,EAAU,gBAAgB,KAAA,KACzB,kBAAC,KAAD;IAAG,WAAU;cAAb;KACG,EAAU;KAAa;KACvB,EAAU,gBAAgB,IACvB,EAAG,uBAAuB,SAAS,CAAC,aAAa,GACjD,EAAG,2BAA2B,UAAU,CAAC,aAAa;KACxD;;GAIN,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,KAAD;KAAG,WAAU;eAAb;MACG,EAAG,kBAAkB,UAAU;MAAC;MAAE,IAAI,KAAK,EAAU,UAAU,CAAC,oBAAoB;MACnF;;IACA,CAAA;GAGL,MAAgB,KAAU,MACzB,kBAAC,OAAD;IAAK,WAAU;cAAf,CACG,KACC,kBAAC,UAAD;KACE,MAAK;KACL,UAxGQ,MAAwB;AAE1C,MADA,EAAE,iBAAiB,EACf,KACF,EAAO,EAAU;;KAsGT,WAAU;eAWT,EAAG,eAAe,OAAO;KACnB,CAAA,EAEV,KACC,kBAAC,UAAD;KACE,MAAK;KACL,UAnHU,MAAwB;AAE5C,MADA,EAAE,iBAAiB,EACf,KACF,EAAS,EAAU;;KAiHX,WAAU;eAWT,EAAG,iBAAiB,SAAS;KACvB,CAAA,CAEP;;GAEJ"}
@@ -8,82 +8,86 @@ import { useEffect as s, useMemo as c, useState as l } from "react";
8
8
  import { Building as u, Home as d, Loader2 as f } from "lucide-react";
9
9
  import { Fragment as p, jsx as m, jsxs as h } from "react/jsx-runtime";
10
10
  //#region src/organization-management/modules/workspaces/components/WorkspaceForm.tsx
11
- function g({ workspace: g, tenantId: _, tenantName: v, organizationId: y, organizationName: b, showOrganizationSelector: x = !1, onSubmit: S, onCancel: C, loading: w }) {
12
- let T = t(), [E, D] = l({
11
+ function g({ workspace: g, tenantId: _, organizationId: v, organizationName: y, showOrganizationSelector: b = !1, onSubmit: x, onCancel: S, loading: C }) {
12
+ let w = t(), [T, E] = l({
13
13
  name: g?.name || "",
14
14
  slug: g?.slug || "",
15
- type: g?.type || "PERSONAL",
16
15
  tenantId: _ || g?.tenantId || "",
17
- organizationId: y || g?.organizationId || ""
18
- }), [O, k] = l({}), A = !g && x && !_, j = !g && x && !y, { tenants: M, loading: N } = r(100, 0, A), { organizations: P, loading: F } = e(E.tenantId ? { tenantId: E.tenantId } : void 0, 100, 0, j), { allowedIds: I, loading: L } = n(c(() => P.map((e) => e.id), [P]), "workspace", "create"), R = !g && x && !y, z = c(() => R ? P.filter((e) => I.has(e.id)) : P, [
16
+ organizationId: v || g?.organizationId || ""
17
+ }), [D, O] = l({}), k = !g && b && !_, A = !g && b && !v, { tenants: j, loading: M } = r(100, 0, k), N = k && j.length > 1;
18
+ s(() => {
19
+ if (!k || T.tenantId || j.length === 0) return;
20
+ let e = j.find((e) => e.type === "SHARED")?.id ?? j[0]?.id;
21
+ e && E((t) => t.tenantId ? t : {
22
+ ...t,
23
+ tenantId: e
24
+ });
25
+ }, [
26
+ k,
27
+ j,
28
+ T.tenantId
29
+ ]);
30
+ let { organizations: P, loading: F } = e(T.tenantId ? { tenantId: T.tenantId } : void 0, 100, 0, A), { allowedIds: I, loading: L } = n(c(() => P.map((e) => e.id), [P]), "workspace", "create"), R = !g && b && !v, z = c(() => R ? P.filter((e) => I.has(e.id)) : P, [
19
31
  P,
20
32
  I,
21
33
  R
22
34
  ]);
23
35
  s(() => {
24
- _ && _ !== E.tenantId && D((e) => ({
36
+ _ && _ !== T.tenantId && E((e) => ({
25
37
  ...e,
26
38
  tenantId: _
27
39
  }));
28
- }, [E.tenantId, _]), s(() => {
29
- y && y !== E.organizationId && D((e) => ({
40
+ }, [T.tenantId, _]), s(() => {
41
+ v && v !== T.organizationId && E((e) => ({
30
42
  ...e,
31
- organizationId: y
43
+ organizationId: v
32
44
  }));
33
- }, [E.organizationId, y]), s(() => {
34
- !x || y || g || D((e) => !e.organizationId || z.some((t) => t.id === e.organizationId) ? e : {
45
+ }, [T.organizationId, v]), s(() => {
46
+ !b || v || g || E((e) => !e.organizationId || z.some((t) => t.id === e.organizationId) ? e : {
35
47
  ...e,
36
48
  organizationId: ""
37
49
  });
38
50
  }, [
39
- y,
51
+ v,
40
52
  z,
41
- x,
53
+ b,
42
54
  g
43
55
  ]);
44
- let B = c(() => v || (M.find((e) => e.id === E.tenantId)?.name ?? E.tenantId), [
45
- E.tenantId,
46
- v,
47
- M
48
- ]), V = c(() => b || (z.find((e) => e.id === E.organizationId)?.name ?? E.organizationId), [
49
- E.organizationId,
50
- b,
56
+ let B = c(() => y || (z.find((e) => e.id === T.organizationId)?.name ?? T.organizationId), [
57
+ T.organizationId,
58
+ y,
51
59
  z
52
- ]), H = () => {
60
+ ]), V = () => {
53
61
  try {
54
- return (g ? o : a).parse(E), k({}), !0;
62
+ return (g ? o : a).parse(T), O({}), !0;
55
63
  } catch (e) {
56
64
  if (e instanceof i) {
57
65
  let t = {};
58
66
  e.issues.forEach((e) => {
59
67
  let n = e.path.join(".");
60
68
  t[n] = e.message;
61
- }), k(t);
69
+ }), O(t);
62
70
  }
63
71
  return !1;
64
72
  }
65
73
  };
66
74
  return /* @__PURE__ */ h("form", {
67
75
  onSubmit: async (e) => {
68
- e.preventDefault(), H() && await S(g ? {
69
- name: E.name === g.name ? void 0 : E.name,
70
- type: E.type === g.type ? void 0 : E.type
71
- } : {
72
- tenantId: E.tenantId,
73
- organizationId: E.organizationId,
74
- name: E.name,
75
- slug: E.slug,
76
- type: E.type || void 0
76
+ e.preventDefault(), V() && await x(g ? { name: T.name === g.name ? void 0 : T.name } : {
77
+ tenantId: T.tenantId,
78
+ organizationId: T.organizationId,
79
+ name: T.name,
80
+ slug: T.slug
77
81
  });
78
82
  },
79
83
  className: "space-y-6",
80
84
  children: [
81
- g ? null : /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ h("div", { children: [
85
+ g ? null : /* @__PURE__ */ h(p, { children: [N ? /* @__PURE__ */ h("div", { children: [
82
86
  /* @__PURE__ */ h("label", {
83
87
  htmlFor: "tenantId",
84
88
  className: "mb-1 block text-sm font-medium text-[var(--color-text-primary)]",
85
89
  children: [
86
- T("organizations.form.tenant", "Tenant"),
90
+ w("organizations.form.tenant", "Tenant"),
87
91
  " ",
88
92
  /* @__PURE__ */ m("span", {
89
93
  className: "text-[var(--color-status-error-text)]",
@@ -91,24 +95,24 @@ function g({ workspace: g, tenantId: _, tenantName: v, organizationId: y, organi
91
95
  })
92
96
  ]
93
97
  }),
94
- x && !_ ? /* @__PURE__ */ h("div", {
98
+ /* @__PURE__ */ h("div", {
95
99
  className: "relative",
96
100
  children: [
97
101
  /* @__PURE__ */ h("select", {
98
102
  id: "tenantId",
99
- value: E.tenantId,
100
- onChange: (e) => D((t) => ({
103
+ value: T.tenantId,
104
+ onChange: (e) => E((t) => ({
101
105
  ...t,
102
106
  tenantId: e.target.value,
103
107
  organizationId: ""
104
108
  })),
105
109
  className: "w-full appearance-none rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] py-2 pl-10 pr-10 text-[var(--color-text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]",
106
- disabled: w || N,
110
+ disabled: C || M,
107
111
  required: !0,
108
112
  children: [/* @__PURE__ */ m("option", {
109
113
  value: "",
110
- children: T("workspaces.form.selectTenant", "Select a tenant...")
111
- }), M.map((e) => /* @__PURE__ */ h("option", {
114
+ children: w("workspaces.form.selectTenant", "Select a tenant...")
115
+ }), j.map((e) => /* @__PURE__ */ h("option", {
112
116
  value: e.id,
113
117
  children: [
114
118
  e.name,
@@ -137,7 +141,7 @@ function g({ workspace: g, tenantId: _, tenantName: v, organizationId: y, organi
137
141
  })
138
142
  })
139
143
  }),
140
- N ? /* @__PURE__ */ m("div", {
144
+ M ? /* @__PURE__ */ m("div", {
141
145
  className: "absolute right-10 top-1/2 -translate-y-1/2",
142
146
  children: /* @__PURE__ */ m(f, {
143
147
  size: 16,
@@ -145,41 +149,17 @@ function g({ workspace: g, tenantId: _, tenantName: v, organizationId: y, organi
145
149
  })
146
150
  }) : null
147
151
  ]
148
- }) : /* @__PURE__ */ h("div", {
149
- className: "relative",
150
- children: [/* @__PURE__ */ m("input", {
151
- id: "tenantId",
152
- type: "text",
153
- value: B,
154
- "aria-label": T("organizations.form.tenant", "Tenant"),
155
- onChange: (e) => D((t) => ({
156
- ...t,
157
- tenantId: e.target.value
158
- })),
159
- className: "w-full rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] py-2 pl-10 pr-4 text-[var(--color-text-primary)] placeholder:text-[var(--color-text-muted)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]",
160
- placeholder: T("organizations.form.tenantPlaceholder", "Enter tenant ID"),
161
- disabled: w || !!_,
162
- required: !0,
163
- autoComplete: "off"
164
- }), /* @__PURE__ */ m(d, {
165
- size: 18,
166
- className: "absolute left-3 top-1/2 -translate-y-1/2 text-[var(--color-text-muted)]"
167
- })]
168
152
  }),
169
- (_ || E.tenantId) && /* @__PURE__ */ m("p", {
170
- className: "mt-1 text-xs text-[var(--color-text-muted)]",
171
- children: T("workspaces.form.creatingUnderTenant", "Creating workspace under the selected tenant.")
172
- }),
173
- O.tenantId ? /* @__PURE__ */ m("p", {
153
+ D.tenantId ? /* @__PURE__ */ m("p", {
174
154
  className: "mt-1 text-sm text-[var(--color-status-error-text)]",
175
- children: O.tenantId
155
+ children: D.tenantId
176
156
  }) : null
177
- ] }), /* @__PURE__ */ h("div", { children: [
157
+ ] }) : null, /* @__PURE__ */ h("div", { children: [
178
158
  /* @__PURE__ */ h("label", {
179
159
  htmlFor: "organizationId",
180
160
  className: "mb-1 block text-sm font-medium text-[var(--color-text-primary)]",
181
161
  children: [
182
- T("common.organization", "Organization"),
162
+ w("common.organization", "Organization"),
183
163
  " ",
184
164
  /* @__PURE__ */ m("span", {
185
165
  className: "text-[var(--color-status-error-text)]",
@@ -187,22 +167,22 @@ function g({ workspace: g, tenantId: _, tenantName: v, organizationId: y, organi
187
167
  })
188
168
  ]
189
169
  }),
190
- x && !y ? /* @__PURE__ */ h("div", {
170
+ b && !v ? /* @__PURE__ */ h("div", {
191
171
  className: "relative",
192
172
  children: [
193
173
  /* @__PURE__ */ h("select", {
194
174
  id: "organizationId",
195
- value: E.organizationId,
196
- onChange: (e) => D((t) => ({
175
+ value: T.organizationId,
176
+ onChange: (e) => E((t) => ({
197
177
  ...t,
198
178
  organizationId: e.target.value
199
179
  })),
200
180
  className: "w-full appearance-none rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] py-2 pl-10 pr-10 text-[var(--color-text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]",
201
- disabled: w || F || L || !E.tenantId,
181
+ disabled: C || F || L || !T.tenantId,
202
182
  required: !0,
203
183
  children: [/* @__PURE__ */ m("option", {
204
184
  value: "",
205
- children: E.tenantId ? z.length === 0 && !F && !L ? T("workspaces.form.noOrganizationsAvailable", "No organizations available — you need workspace create permission") : T("workspaces.form.selectOrganization", "Select an organization...") : T("workspaces.form.selectTenantFirst", "Select a tenant first")
185
+ children: T.tenantId ? z.length === 0 && !F && !L ? w("workspaces.form.noOrganizationsAvailable", "No organizations available — you need workspace create permission") : w("workspaces.form.selectOrganization", "Select an organization...") : w("workspaces.form.selectTenantFirst", "Select a tenant first")
206
186
  }), z.map((e) => /* @__PURE__ */ h("option", {
207
187
  value: e.id,
208
188
  children: [
@@ -245,15 +225,15 @@ function g({ workspace: g, tenantId: _, tenantName: v, organizationId: y, organi
245
225
  children: [/* @__PURE__ */ m("input", {
246
226
  id: "organizationId",
247
227
  type: "text",
248
- value: V,
249
- "aria-label": T("common.organization", "Organization"),
250
- onChange: (e) => D((t) => ({
228
+ value: B,
229
+ "aria-label": w("common.organization", "Organization"),
230
+ onChange: (e) => E((t) => ({
251
231
  ...t,
252
232
  organizationId: e.target.value
253
233
  })),
254
234
  className: "w-full rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] py-2 pl-10 pr-4 text-[var(--color-text-primary)] placeholder:text-[var(--color-text-muted)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]",
255
- placeholder: T("workspaces.form.orgIdPlaceholder", "Enter organization ID"),
256
- disabled: w || !!y,
235
+ placeholder: w("workspaces.form.orgIdPlaceholder", "Enter organization ID"),
236
+ disabled: C || !!v,
257
237
  required: !0,
258
238
  autoComplete: "off"
259
239
  }), /* @__PURE__ */ m(u, {
@@ -261,13 +241,13 @@ function g({ workspace: g, tenantId: _, tenantName: v, organizationId: y, organi
261
241
  className: "absolute left-3 top-1/2 -translate-y-1/2 text-[var(--color-text-muted)]"
262
242
  })]
263
243
  }),
264
- (y || E.organizationId) && /* @__PURE__ */ m("p", {
244
+ (v || T.organizationId) && /* @__PURE__ */ m("p", {
265
245
  className: "mt-1 text-xs text-[var(--color-text-muted)]",
266
- children: T("workspaces.form.creatingUnderOrg", "Creating workspace under the selected organization.")
246
+ children: w("workspaces.form.creatingUnderOrg", "Creating workspace under the selected organization.")
267
247
  }),
268
- O.organizationId ? /* @__PURE__ */ m("p", {
248
+ D.organizationId ? /* @__PURE__ */ m("p", {
269
249
  className: "mt-1 text-sm text-[var(--color-status-error-text)]",
270
- children: O.organizationId
250
+ children: D.organizationId
271
251
  }) : null
272
252
  ] })] }),
273
253
  /* @__PURE__ */ h("div", { children: [
@@ -275,7 +255,7 @@ function g({ workspace: g, tenantId: _, tenantName: v, organizationId: y, organi
275
255
  htmlFor: "name",
276
256
  className: "mb-1 block text-sm font-medium text-[var(--color-text-primary)]",
277
257
  children: [
278
- T("workspaces.form.name", "Workspace Name"),
258
+ w("workspaces.form.name", "Workspace Name"),
279
259
  " ",
280
260
  /* @__PURE__ */ m("span", {
281
261
  className: "text-[var(--color-status-error-text)]",
@@ -286,21 +266,21 @@ function g({ workspace: g, tenantId: _, tenantName: v, organizationId: y, organi
286
266
  /* @__PURE__ */ m("input", {
287
267
  id: "name",
288
268
  type: "text",
289
- value: E.name,
290
- "aria-label": T("workspaces.form.name", "Workspace Name"),
291
- onChange: (e) => D((t) => ({
269
+ value: T.name,
270
+ "aria-label": w("workspaces.form.name", "Workspace Name"),
271
+ onChange: (e) => E((t) => ({
292
272
  ...t,
293
273
  name: e.target.value
294
274
  })),
295
275
  className: "w-full rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] px-3 py-2 text-[var(--color-text-primary)] placeholder:text-[var(--color-text-muted)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]",
296
- placeholder: T("workspaces.form.namePlaceholder", "Enter workspace name"),
297
- disabled: w,
276
+ placeholder: w("workspaces.form.namePlaceholder", "Enter workspace name"),
277
+ disabled: C,
298
278
  required: !0,
299
279
  autoComplete: "organization-title"
300
280
  }),
301
- O.name ? /* @__PURE__ */ m("p", {
281
+ D.name ? /* @__PURE__ */ m("p", {
302
282
  className: "mt-1 text-sm text-[var(--color-status-error-text)]",
303
- children: O.name
283
+ children: D.name
304
284
  }) : null
305
285
  ] }),
306
286
  /* @__PURE__ */ h("div", { children: [
@@ -308,7 +288,7 @@ function g({ workspace: g, tenantId: _, tenantName: v, organizationId: y, organi
308
288
  htmlFor: "slug",
309
289
  className: "mb-1 block text-sm font-medium text-[var(--color-text-primary)]",
310
290
  children: [
311
- T("common.slug", "Slug"),
291
+ w("common.slug", "Slug"),
312
292
  " ",
313
293
  /* @__PURE__ */ m("span", {
314
294
  className: "text-[var(--color-status-error-text)]",
@@ -319,71 +299,43 @@ function g({ workspace: g, tenantId: _, tenantName: v, organizationId: y, organi
319
299
  /* @__PURE__ */ m("input", {
320
300
  id: "slug",
321
301
  type: "text",
322
- value: E.slug,
323
- "aria-label": T("common.slug", "Slug"),
324
- onChange: (e) => D((t) => ({
302
+ value: T.slug,
303
+ "aria-label": w("common.slug", "Slug"),
304
+ onChange: (e) => E((t) => ({
325
305
  ...t,
326
306
  slug: e.target.value.toLowerCase().replace(/\s+/g, "-")
327
307
  })),
328
308
  className: "w-full rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] px-3 py-2 text-[var(--color-text-primary)] placeholder:text-[var(--color-text-muted)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]",
329
- placeholder: T("workspaces.form.slugPlaceholder", "workspace-slug"),
330
- disabled: w || !!g,
309
+ placeholder: w("workspaces.form.slugPlaceholder", "workspace-slug"),
310
+ disabled: C || !!g,
331
311
  required: !g,
332
312
  autoComplete: "off"
333
313
  }),
334
314
  /* @__PURE__ */ m("p", {
335
315
  className: "mt-1 text-xs text-[var(--color-text-muted)]",
336
- children: T("organizations.form.slugImmutable", "Lowercase letters, numbers, and hyphens only. Cannot be changed after creation.")
316
+ children: w("organizations.form.slugImmutable", "Lowercase letters, numbers, and hyphens only. Cannot be changed after creation.")
337
317
  }),
338
- O.slug ? /* @__PURE__ */ m("p", {
318
+ D.slug ? /* @__PURE__ */ m("p", {
339
319
  className: "mt-1 text-sm text-[var(--color-status-error-text)]",
340
- children: O.slug
320
+ children: D.slug
341
321
  }) : null
342
322
  ] }),
343
- /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("label", {
344
- htmlFor: "type",
345
- className: "mb-1 block text-sm font-medium text-[var(--color-text-primary)]",
346
- children: T("workspaces.list.column.type", "Type")
347
- }), /* @__PURE__ */ h("select", {
348
- id: "type",
349
- value: E.type,
350
- onChange: (e) => D((t) => ({
351
- ...t,
352
- type: e.target.value
353
- })),
354
- className: "w-full rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] px-3 py-2 text-[var(--color-text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]",
355
- disabled: w,
356
- children: [
357
- /* @__PURE__ */ m("option", {
358
- value: "PERSONAL",
359
- children: T("workspaces.type.personal", "Personal")
360
- }),
361
- /* @__PURE__ */ m("option", {
362
- value: "TEAM",
363
- children: T("workspaces.type.team", "Team")
364
- }),
365
- /* @__PURE__ */ m("option", {
366
- value: "ENTERPRISE",
367
- children: T("workspaces.type.enterprise", "Enterprise")
368
- })
369
- ]
370
- })] }),
371
323
  /* @__PURE__ */ h("div", {
372
324
  className: "flex flex-col gap-3 border-t border-[var(--color-border-default)] pt-4 sm:flex-row",
373
325
  children: [/* @__PURE__ */ h("button", {
374
326
  type: "submit",
375
- disabled: w,
327
+ disabled: C,
376
328
  className: "inline-flex items-center justify-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-6 py-2.5 font-medium text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90 hover:scale-[1.02] active:scale-[0.98] disabled:cursor-not-allowed disabled:opacity-50 sm:min-w-[220px]",
377
- children: [w ? /* @__PURE__ */ m(f, {
329
+ children: [C ? /* @__PURE__ */ m(f, {
378
330
  size: 16,
379
331
  className: "animate-spin"
380
- }) : null, g ? T("workspaces.form.updateSubmit", "Update Workspace") : T("workspaces.create.button", "Create Workspace")]
332
+ }) : null, g ? w("workspaces.form.updateSubmit", "Update Workspace") : w("workspaces.create.button", "Create Workspace")]
381
333
  }), /* @__PURE__ */ m("button", {
382
334
  type: "button",
383
- onClick: C,
384
- disabled: w,
335
+ onClick: S,
336
+ disabled: C,
385
337
  className: "rounded-lg border border-[var(--color-border-default)] bg-transparent px-6 py-2.5 font-medium text-[var(--color-text-primary)] transition-all duration-200 hover:bg-[var(--color-bg-subtle)] active:scale-[0.98] disabled:cursor-not-allowed disabled:opacity-50 sm:min-w-[140px]",
386
- children: T("common.cancel", "Cancel")
338
+ children: w("common.cancel", "Cancel")
387
339
  })]
388
340
  })
389
341
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"WorkspaceForm.js","names":[],"sources":["../../../../../src/organization-management/modules/workspaces/components/WorkspaceForm.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport { Building, Home, Loader2 } from 'lucide-react';\nimport { ZodError } from 'zod';\nimport type { CreateWorkspaceInput, UpdateWorkspaceInput, Workspace } from '../types';\nimport { createWorkspaceSchema, updateWorkspaceSchema } from '../schemas';\nimport { useOrganizations } from '../../organizations/hooks/useOrganizations';\nimport { useOrgsWithPermission } from '../../organizations/hooks/useOrgsWithPermission';\nimport { useTenants } from '../hooks/useWorkspaces';\nimport { useTr } from '../../../shared/hooks/useTr';\n\ninterface WorkspaceFormProps {\n workspace?: Workspace | null;\n tenantId?: string;\n tenantName?: string;\n organizationId?: string;\n organizationName?: string;\n showOrganizationSelector?: boolean;\n onSubmit: (data: CreateWorkspaceInput | UpdateWorkspaceInput) => Promise<void>;\n onCancel: () => void;\n loading?: boolean;\n}\n\nexport function WorkspaceForm({\n workspace,\n tenantId,\n tenantName,\n organizationId,\n organizationName,\n showOrganizationSelector = false,\n onSubmit,\n onCancel,\n loading,\n}: WorkspaceFormProps) {\n const tr = useTr();\n const [formData, setFormData] = useState({\n // react-doctor-disable-next-line react-doctor/no-event-handler\n name: workspace?.name || '',\n slug: workspace?.slug || '',\n type: workspace?.type || 'PERSONAL',\n // react-doctor-disable-next-line react-doctor/no-event-handler\n tenantId: tenantId || workspace?.tenantId || '',\n // react-doctor-disable-next-line react-doctor/no-event-handler\n organizationId: organizationId || workspace?.organizationId || '',\n });\n\n const [errors, setErrors] = useState<Record<string, string>>({});\n\n const shouldLoadTenants = !workspace && showOrganizationSelector && !tenantId;\n const shouldLoadOrganizations = !workspace && showOrganizationSelector && !organizationId;\n\n const { tenants, loading: tenantsLoading } = useTenants(100, 0, shouldLoadTenants);\n const { organizations, loading: organizationsLoading } = useOrganizations(\n formData.tenantId ? { tenantId: formData.tenantId } : undefined,\n 100,\n 0,\n shouldLoadOrganizations\n );\n\n // Hide orgs where the user can't actually create a workspace, so the\n // dropdown only surfaces options the gateway @rbac(workspace:create) will\n // accept. Membership alone isn't enough — a Viewer of an org is a member\n // but has workspace=VIEWER (no create). The bulk checkPermissions call is\n // one round-trip regardless of how many orgs are on the list.\n const allOrgIds = useMemo(\n () => organizations.map((organization) => organization.id),\n [organizations]\n );\n const { allowedIds: workspaceCreateAllowedOrgIds, loading: permissionCheckLoading } =\n useOrgsWithPermission(allOrgIds, 'workspace', 'create');\n const filterByPermission = !workspace && showOrganizationSelector && !organizationId;\n const permittedOrganizations = useMemo(\n () =>\n filterByPermission\n ? organizations.filter((organization) => workspaceCreateAllowedOrgIds.has(organization.id))\n : organizations,\n [organizations, workspaceCreateAllowedOrgIds, filterByPermission]\n );\n\n useEffect(() => {\n // react-doctor-disable-next-line react-doctor/no-event-handler\n if (tenantId && tenantId !== formData.tenantId) {\n setFormData((previousState) => ({ ...previousState, tenantId }));\n }\n }, [formData.tenantId, tenantId]);\n\n useEffect(() => {\n // react-doctor-disable-next-line react-doctor/no-event-handler\n if (organizationId && organizationId !== formData.organizationId) {\n setFormData((previousState) => ({ ...previousState, organizationId }));\n }\n }, [formData.organizationId, organizationId]);\n\n useEffect(() => {\n if (!showOrganizationSelector || organizationId || workspace) {\n return;\n }\n\n setFormData((previousState) => {\n if (!previousState.organizationId) {\n return previousState;\n }\n\n const hasMatchingOrganization = permittedOrganizations.some(\n (organization) => organization.id === previousState.organizationId\n );\n\n if (hasMatchingOrganization) {\n return previousState;\n }\n\n return { ...previousState, organizationId: '' };\n });\n }, [organizationId, permittedOrganizations, showOrganizationSelector, workspace]);\n\n const selectedTenantLabel = useMemo(() => {\n if (tenantName) return tenantName;\n\n const selectedTenant = tenants.find((tenant) => tenant.id === formData.tenantId);\n return selectedTenant?.name ?? formData.tenantId;\n }, [formData.tenantId, tenantName, tenants]);\n\n const selectedOrganizationLabel = useMemo(() => {\n if (organizationName) return organizationName;\n\n const selectedOrganization = permittedOrganizations.find(\n (organization) => organization.id === formData.organizationId\n );\n return selectedOrganization?.name ?? formData.organizationId;\n }, [formData.organizationId, organizationName, permittedOrganizations]);\n\n const validate = () => {\n try {\n const schema = workspace ? updateWorkspaceSchema : createWorkspaceSchema;\n schema.parse(formData);\n setErrors({});\n return true;\n } catch (validationError) {\n if (validationError instanceof ZodError) {\n const nextErrors: Record<string, string> = {};\n validationError.issues.forEach((issue) => {\n const path = issue.path.join('.');\n nextErrors[path] = issue.message;\n });\n setErrors(nextErrors);\n }\n\n return false;\n }\n };\n\n const handleSubmit = async (event: React.FormEvent) => {\n event.preventDefault();\n\n if (!validate()) {\n return;\n }\n\n const submitData = workspace\n ? {\n name: formData.name !== workspace.name ? formData.name : undefined,\n type: formData.type !== workspace.type ? formData.type : undefined,\n }\n : {\n tenantId: formData.tenantId,\n organizationId: formData.organizationId,\n name: formData.name,\n slug: formData.slug,\n type: formData.type || undefined,\n };\n\n await onSubmit(submitData);\n };\n\n return (\n <form onSubmit={handleSubmit} className=\"space-y-6\">\n {!workspace ? (\n <>\n <div>\n <label\n htmlFor=\"tenantId\"\n className=\"mb-1 block text-sm font-medium text-[var(--color-text-primary)]\"\n >\n {tr('organizations.form.tenant', 'Tenant')}{' '}\n <span className=\"text-[var(--color-status-error-text)]\">*</span>\n </label>\n\n {showOrganizationSelector && !tenantId ? (\n <div className=\"relative\">\n <select\n id=\"tenantId\"\n value={formData.tenantId}\n onChange={(event) =>\n setFormData((previousState) => ({\n ...previousState,\n tenantId: event.target.value,\n organizationId: '',\n }))\n }\n className=\"w-full appearance-none rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] py-2 pl-10 pr-10 text-[var(--color-text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]\"\n disabled={loading || tenantsLoading}\n required\n >\n <option value=\"\">\n {tr('workspaces.form.selectTenant', 'Select a tenant...')}\n </option>\n {tenants.map((tenant) => (\n <option key={tenant.id} value={tenant.id}>\n {tenant.name} ({tenant.slug})\n </option>\n ))}\n </select>\n <Home\n size={18}\n className=\"pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-[var(--color-text-muted)]\"\n />\n <div className=\"pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-[var(--color-text-muted)]\">\n <svg className=\"size-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 9l-7 7-7-7\"\n />\n </svg>\n </div>\n {tenantsLoading ? (\n <div className=\"absolute right-10 top-1/2 -translate-y-1/2\">\n <Loader2 size={16} className=\"animate-spin text-[var(--color-text-muted)]\" />\n </div>\n ) : null}\n </div>\n ) : (\n <div className=\"relative\">\n <input\n id=\"tenantId\"\n type=\"text\"\n value={selectedTenantLabel}\n aria-label={tr('organizations.form.tenant', 'Tenant')}\n onChange={(event) =>\n setFormData((previousState) => ({\n ...previousState,\n tenantId: event.target.value,\n }))\n }\n className=\"w-full rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] py-2 pl-10 pr-4 text-[var(--color-text-primary)] placeholder:text-[var(--color-text-muted)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]\"\n placeholder={tr('organizations.form.tenantPlaceholder', 'Enter tenant ID')}\n disabled={loading || Boolean(tenantId)}\n required\n autoComplete=\"off\"\n />\n <Home\n size={18}\n className=\"absolute left-3 top-1/2 -translate-y-1/2 text-[var(--color-text-muted)]\"\n />\n </div>\n )}\n\n {(tenantId || formData.tenantId) && (\n <p className=\"mt-1 text-xs text-[var(--color-text-muted)]\">\n {tr(\n 'workspaces.form.creatingUnderTenant',\n 'Creating workspace under the selected tenant.'\n )}\n </p>\n )}\n {errors.tenantId ? (\n <p className=\"mt-1 text-sm text-[var(--color-status-error-text)]\">\n {errors.tenantId}\n </p>\n ) : null}\n </div>\n\n <div>\n <label\n htmlFor=\"organizationId\"\n className=\"mb-1 block text-sm font-medium text-[var(--color-text-primary)]\"\n >\n {tr('common.organization', 'Organization')}{' '}\n <span className=\"text-[var(--color-status-error-text)]\">*</span>\n </label>\n\n {showOrganizationSelector && !organizationId ? (\n <div className=\"relative\">\n <select\n id=\"organizationId\"\n value={formData.organizationId}\n onChange={(event) =>\n setFormData((previousState) => ({\n ...previousState,\n organizationId: event.target.value,\n }))\n }\n className=\"w-full appearance-none rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] py-2 pl-10 pr-10 text-[var(--color-text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]\"\n disabled={\n loading || organizationsLoading || permissionCheckLoading || !formData.tenantId\n }\n required\n >\n <option value=\"\">\n {!formData.tenantId\n ? tr('workspaces.form.selectTenantFirst', 'Select a tenant first')\n : permittedOrganizations.length === 0 &&\n !organizationsLoading &&\n !permissionCheckLoading\n ? tr(\n 'workspaces.form.noOrganizationsAvailable',\n 'No organizations available — you need workspace create permission'\n )\n : tr('workspaces.form.selectOrganization', 'Select an organization...')}\n </option>\n {permittedOrganizations.map((organization) => (\n <option key={organization.id} value={organization.id}>\n {organization.name} ({organization.slug})\n </option>\n ))}\n </select>\n <Building\n size={18}\n className=\"pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-[var(--color-text-muted)]\"\n />\n <div className=\"pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-[var(--color-text-muted)]\">\n <svg className=\"size-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 9l-7 7-7-7\"\n />\n </svg>\n </div>\n {organizationsLoading || permissionCheckLoading ? (\n <div className=\"absolute right-10 top-1/2 -translate-y-1/2\">\n <Loader2 size={16} className=\"animate-spin text-[var(--color-text-muted)]\" />\n </div>\n ) : null}\n </div>\n ) : (\n <div className=\"relative\">\n <input\n id=\"organizationId\"\n type=\"text\"\n value={selectedOrganizationLabel}\n aria-label={tr('common.organization', 'Organization')}\n onChange={(event) =>\n setFormData((previousState) => ({\n ...previousState,\n organizationId: event.target.value,\n }))\n }\n className=\"w-full rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] py-2 pl-10 pr-4 text-[var(--color-text-primary)] placeholder:text-[var(--color-text-muted)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]\"\n placeholder={tr('workspaces.form.orgIdPlaceholder', 'Enter organization ID')}\n disabled={loading || Boolean(organizationId)}\n required\n autoComplete=\"off\"\n />\n <Building\n size={18}\n className=\"absolute left-3 top-1/2 -translate-y-1/2 text-[var(--color-text-muted)]\"\n />\n </div>\n )}\n\n {(organizationId || formData.organizationId) && (\n <p className=\"mt-1 text-xs text-[var(--color-text-muted)]\">\n {tr(\n 'workspaces.form.creatingUnderOrg',\n 'Creating workspace under the selected organization.'\n )}\n </p>\n )}\n {errors.organizationId ? (\n <p className=\"mt-1 text-sm text-[var(--color-status-error-text)]\">\n {errors.organizationId}\n </p>\n ) : null}\n </div>\n </>\n ) : null}\n\n <div>\n <label\n htmlFor=\"name\"\n className=\"mb-1 block text-sm font-medium text-[var(--color-text-primary)]\"\n >\n {tr('workspaces.form.name', 'Workspace Name')}{' '}\n <span className=\"text-[var(--color-status-error-text)]\">*</span>\n </label>\n <input\n id=\"name\"\n type=\"text\"\n value={formData.name}\n aria-label={tr('workspaces.form.name', 'Workspace Name')}\n onChange={(event) =>\n setFormData((previousState) => ({ ...previousState, name: event.target.value }))\n }\n className=\"w-full rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] px-3 py-2 text-[var(--color-text-primary)] placeholder:text-[var(--color-text-muted)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]\"\n placeholder={tr('workspaces.form.namePlaceholder', 'Enter workspace name')}\n disabled={loading}\n required\n autoComplete=\"organization-title\"\n />\n {errors.name ? (\n <p className=\"mt-1 text-sm text-[var(--color-status-error-text)]\">{errors.name}</p>\n ) : null}\n </div>\n\n <div>\n <label\n htmlFor=\"slug\"\n className=\"mb-1 block text-sm font-medium text-[var(--color-text-primary)]\"\n >\n {tr('common.slug', 'Slug')}{' '}\n <span className=\"text-[var(--color-status-error-text)]\">*</span>\n </label>\n <input\n id=\"slug\"\n type=\"text\"\n value={formData.slug}\n aria-label={tr('common.slug', 'Slug')}\n onChange={(event) =>\n setFormData((previousState) => ({\n ...previousState,\n slug: event.target.value.toLowerCase().replace(/\\s+/g, '-'),\n }))\n }\n className=\"w-full rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] px-3 py-2 text-[var(--color-text-primary)] placeholder:text-[var(--color-text-muted)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]\"\n placeholder={tr('workspaces.form.slugPlaceholder', 'workspace-slug')}\n disabled={loading || Boolean(workspace)}\n required={!workspace}\n autoComplete=\"off\"\n />\n <p className=\"mt-1 text-xs text-[var(--color-text-muted)]\">\n {tr(\n 'organizations.form.slugImmutable',\n 'Lowercase letters, numbers, and hyphens only. Cannot be changed after creation.'\n )}\n </p>\n {errors.slug ? (\n <p className=\"mt-1 text-sm text-[var(--color-status-error-text)]\">{errors.slug}</p>\n ) : null}\n </div>\n\n <div>\n <label\n htmlFor=\"type\"\n className=\"mb-1 block text-sm font-medium text-[var(--color-text-primary)]\"\n >\n {tr('workspaces.list.column.type', 'Type')}\n </label>\n <select\n id=\"type\"\n value={formData.type}\n onChange={(event) =>\n setFormData((previousState) => ({ ...previousState, type: event.target.value }))\n }\n className=\"w-full rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] px-3 py-2 text-[var(--color-text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]\"\n disabled={loading}\n >\n <option value=\"PERSONAL\">{tr('workspaces.type.personal', 'Personal')}</option>\n <option value=\"TEAM\">{tr('workspaces.type.team', 'Team')}</option>\n <option value=\"ENTERPRISE\">{tr('workspaces.type.enterprise', 'Enterprise')}</option>\n </select>\n </div>\n\n <div className=\"flex flex-col gap-3 border-t border-[var(--color-border-default)] pt-4 sm:flex-row\">\n <button\n type=\"submit\"\n disabled={loading}\n className=\"inline-flex items-center justify-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-6 py-2.5 font-medium text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90 hover:scale-[1.02] active:scale-[0.98] disabled:cursor-not-allowed disabled:opacity-50 sm:min-w-[220px]\"\n >\n {loading ? <Loader2 size={16} className=\"animate-spin\" /> : null}\n {workspace\n ? tr('workspaces.form.updateSubmit', 'Update Workspace')\n : tr('workspaces.create.button', 'Create Workspace')}\n </button>\n\n <button\n type=\"button\"\n onClick={onCancel}\n disabled={loading}\n className=\"rounded-lg border border-[var(--color-border-default)] bg-transparent px-6 py-2.5 font-medium text-[var(--color-text-primary)] transition-all duration-200 hover:bg-[var(--color-bg-subtle)] active:scale-[0.98] disabled:cursor-not-allowed disabled:opacity-50 sm:min-w-[140px]\"\n >\n {tr('common.cancel', 'Cancel')}\n </button>\n </div>\n </form>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"WorkspaceForm.js","names":[],"sources":["../../../../../src/organization-management/modules/workspaces/components/WorkspaceForm.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport { Building, Home, Loader2 } from 'lucide-react';\nimport { ZodError } from 'zod';\nimport type { CreateWorkspaceInput, UpdateWorkspaceInput, Workspace } from '../types';\nimport { createWorkspaceSchema, updateWorkspaceSchema } from '../schemas';\nimport { useOrganizations } from '../../organizations/hooks/useOrganizations';\nimport { useOrgsWithPermission } from '../../organizations/hooks/useOrgsWithPermission';\nimport { useTenants } from '../hooks/useWorkspaces';\nimport { useTr } from '../../../shared/hooks/useTr';\n\ninterface WorkspaceFormProps {\n workspace?: Workspace | null;\n tenantId?: string;\n tenantName?: string;\n organizationId?: string;\n organizationName?: string;\n showOrganizationSelector?: boolean;\n onSubmit: (data: CreateWorkspaceInput | UpdateWorkspaceInput) => Promise<void>;\n onCancel: () => void;\n loading?: boolean;\n}\n\nexport function WorkspaceForm({\n workspace,\n tenantId,\n organizationId,\n organizationName,\n showOrganizationSelector = false,\n onSubmit,\n onCancel,\n loading,\n}: WorkspaceFormProps) {\n const tr = useTr();\n const [formData, setFormData] = useState({\n // react-doctor-disable-next-line react-doctor/no-event-handler\n name: workspace?.name || '',\n slug: workspace?.slug || '',\n // react-doctor-disable-next-line react-doctor/no-event-handler\n tenantId: tenantId || workspace?.tenantId || '',\n // react-doctor-disable-next-line react-doctor/no-event-handler\n organizationId: organizationId || workspace?.organizationId || '',\n });\n\n const [errors, setErrors] = useState<Record<string, string>>({});\n\n const shouldLoadTenants = !workspace && showOrganizationSelector && !tenantId;\n const shouldLoadOrganizations = !workspace && showOrganizationSelector && !organizationId;\n\n const { tenants, loading: tenantsLoading } = useTenants(100, 0, shouldLoadTenants);\n\n // Show the tenant picker only when the user genuinely has more than one\n // tenant to choose between. With a single shared tenant there is nothing to\n // choose, so the picker is hidden and the tenant is auto-selected.\n const showTenantPicker = shouldLoadTenants && tenants.length > 1;\n\n // Auto-select the shared (or only) tenant when there is no explicit tenant\n // and no real choice to make, so the workspace lands in the shared tenant\n // without surfacing a picker.\n useEffect(() => {\n if (!shouldLoadTenants || formData.tenantId || tenants.length === 0) {\n return;\n }\n const sharedTenant = tenants.find((tenant) => tenant.type === 'SHARED');\n const resolved = sharedTenant?.id ?? tenants[0]?.id;\n if (resolved) {\n setFormData((previousState) =>\n previousState.tenantId ? previousState : { ...previousState, tenantId: resolved }\n );\n }\n }, [shouldLoadTenants, tenants, formData.tenantId]);\n const { organizations, loading: organizationsLoading } = useOrganizations(\n formData.tenantId ? { tenantId: formData.tenantId } : undefined,\n 100,\n 0,\n shouldLoadOrganizations\n );\n\n // Hide orgs where the user can't actually create a workspace, so the\n // dropdown only surfaces options the gateway @rbac(workspace:create) will\n // accept. Membership alone isn't enough — a Viewer of an org is a member\n // but has workspace=VIEWER (no create). The bulk checkPermissions call is\n // one round-trip regardless of how many orgs are on the list.\n const allOrgIds = useMemo(\n () => organizations.map((organization) => organization.id),\n [organizations]\n );\n const { allowedIds: workspaceCreateAllowedOrgIds, loading: permissionCheckLoading } =\n useOrgsWithPermission(allOrgIds, 'workspace', 'create');\n const filterByPermission = !workspace && showOrganizationSelector && !organizationId;\n const permittedOrganizations = useMemo(\n () =>\n filterByPermission\n ? organizations.filter((organization) => workspaceCreateAllowedOrgIds.has(organization.id))\n : organizations,\n [organizations, workspaceCreateAllowedOrgIds, filterByPermission]\n );\n\n useEffect(() => {\n // react-doctor-disable-next-line react-doctor/no-event-handler\n if (tenantId && tenantId !== formData.tenantId) {\n setFormData((previousState) => ({ ...previousState, tenantId }));\n }\n }, [formData.tenantId, tenantId]);\n\n useEffect(() => {\n // react-doctor-disable-next-line react-doctor/no-event-handler\n if (organizationId && organizationId !== formData.organizationId) {\n setFormData((previousState) => ({ ...previousState, organizationId }));\n }\n }, [formData.organizationId, organizationId]);\n\n useEffect(() => {\n if (!showOrganizationSelector || organizationId || workspace) {\n return;\n }\n\n setFormData((previousState) => {\n if (!previousState.organizationId) {\n return previousState;\n }\n\n const hasMatchingOrganization = permittedOrganizations.some(\n (organization) => organization.id === previousState.organizationId\n );\n\n if (hasMatchingOrganization) {\n return previousState;\n }\n\n return { ...previousState, organizationId: '' };\n });\n }, [organizationId, permittedOrganizations, showOrganizationSelector, workspace]);\n\n const selectedOrganizationLabel = useMemo(() => {\n if (organizationName) return organizationName;\n\n const selectedOrganization = permittedOrganizations.find(\n (organization) => organization.id === formData.organizationId\n );\n return selectedOrganization?.name ?? formData.organizationId;\n }, [formData.organizationId, organizationName, permittedOrganizations]);\n\n const validate = () => {\n try {\n const schema = workspace ? updateWorkspaceSchema : createWorkspaceSchema;\n schema.parse(formData);\n setErrors({});\n return true;\n } catch (validationError) {\n if (validationError instanceof ZodError) {\n const nextErrors: Record<string, string> = {};\n validationError.issues.forEach((issue) => {\n const path = issue.path.join('.');\n nextErrors[path] = issue.message;\n });\n setErrors(nextErrors);\n }\n\n return false;\n }\n };\n\n const handleSubmit = async (event: React.FormEvent) => {\n event.preventDefault();\n\n if (!validate()) {\n return;\n }\n\n const submitData = workspace\n ? {\n name: formData.name !== workspace.name ? formData.name : undefined,\n }\n : {\n tenantId: formData.tenantId,\n organizationId: formData.organizationId,\n name: formData.name,\n slug: formData.slug,\n };\n\n await onSubmit(submitData);\n };\n\n return (\n <form onSubmit={handleSubmit} className=\"space-y-6\">\n {!workspace ? (\n <>\n {/* Tenant picker — shown ONLY when the user has more than one tenant\n to choose between. For single-tenant (shared) users the tenant is\n auto-selected and no picker is rendered. */}\n {showTenantPicker ? (\n <div>\n <label\n htmlFor=\"tenantId\"\n className=\"mb-1 block text-sm font-medium text-[var(--color-text-primary)]\"\n >\n {tr('organizations.form.tenant', 'Tenant')}{' '}\n <span className=\"text-[var(--color-status-error-text)]\">*</span>\n </label>\n\n <div className=\"relative\">\n <select\n id=\"tenantId\"\n value={formData.tenantId}\n onChange={(event) =>\n setFormData((previousState) => ({\n ...previousState,\n tenantId: event.target.value,\n organizationId: '',\n }))\n }\n className=\"w-full appearance-none rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] py-2 pl-10 pr-10 text-[var(--color-text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]\"\n disabled={loading || tenantsLoading}\n required\n >\n <option value=\"\">\n {tr('workspaces.form.selectTenant', 'Select a tenant...')}\n </option>\n {tenants.map((tenant) => (\n <option key={tenant.id} value={tenant.id}>\n {tenant.name} ({tenant.slug})\n </option>\n ))}\n </select>\n <Home\n size={18}\n className=\"pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-[var(--color-text-muted)]\"\n />\n <div className=\"pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-[var(--color-text-muted)]\">\n <svg className=\"size-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 9l-7 7-7-7\"\n />\n </svg>\n </div>\n {tenantsLoading ? (\n <div className=\"absolute right-10 top-1/2 -translate-y-1/2\">\n <Loader2 size={16} className=\"animate-spin text-[var(--color-text-muted)]\" />\n </div>\n ) : null}\n </div>\n {errors.tenantId ? (\n <p className=\"mt-1 text-sm text-[var(--color-status-error-text)]\">\n {errors.tenantId}\n </p>\n ) : null}\n </div>\n ) : null}\n\n <div>\n <label\n htmlFor=\"organizationId\"\n className=\"mb-1 block text-sm font-medium text-[var(--color-text-primary)]\"\n >\n {tr('common.organization', 'Organization')}{' '}\n <span className=\"text-[var(--color-status-error-text)]\">*</span>\n </label>\n\n {showOrganizationSelector && !organizationId ? (\n <div className=\"relative\">\n <select\n id=\"organizationId\"\n value={formData.organizationId}\n onChange={(event) =>\n setFormData((previousState) => ({\n ...previousState,\n organizationId: event.target.value,\n }))\n }\n className=\"w-full appearance-none rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] py-2 pl-10 pr-10 text-[var(--color-text-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]\"\n disabled={\n loading || organizationsLoading || permissionCheckLoading || !formData.tenantId\n }\n required\n >\n <option value=\"\">\n {!formData.tenantId\n ? tr('workspaces.form.selectTenantFirst', 'Select a tenant first')\n : permittedOrganizations.length === 0 &&\n !organizationsLoading &&\n !permissionCheckLoading\n ? tr(\n 'workspaces.form.noOrganizationsAvailable',\n 'No organizations available — you need workspace create permission'\n )\n : tr('workspaces.form.selectOrganization', 'Select an organization...')}\n </option>\n {permittedOrganizations.map((organization) => (\n <option key={organization.id} value={organization.id}>\n {organization.name} ({organization.slug})\n </option>\n ))}\n </select>\n <Building\n size={18}\n className=\"pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-[var(--color-text-muted)]\"\n />\n <div className=\"pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-[var(--color-text-muted)]\">\n <svg className=\"size-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 9l-7 7-7-7\"\n />\n </svg>\n </div>\n {organizationsLoading || permissionCheckLoading ? (\n <div className=\"absolute right-10 top-1/2 -translate-y-1/2\">\n <Loader2 size={16} className=\"animate-spin text-[var(--color-text-muted)]\" />\n </div>\n ) : null}\n </div>\n ) : (\n <div className=\"relative\">\n <input\n id=\"organizationId\"\n type=\"text\"\n value={selectedOrganizationLabel}\n aria-label={tr('common.organization', 'Organization')}\n onChange={(event) =>\n setFormData((previousState) => ({\n ...previousState,\n organizationId: event.target.value,\n }))\n }\n className=\"w-full rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] py-2 pl-10 pr-4 text-[var(--color-text-primary)] placeholder:text-[var(--color-text-muted)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]\"\n placeholder={tr('workspaces.form.orgIdPlaceholder', 'Enter organization ID')}\n disabled={loading || Boolean(organizationId)}\n required\n autoComplete=\"off\"\n />\n <Building\n size={18}\n className=\"absolute left-3 top-1/2 -translate-y-1/2 text-[var(--color-text-muted)]\"\n />\n </div>\n )}\n\n {(organizationId || formData.organizationId) && (\n <p className=\"mt-1 text-xs text-[var(--color-text-muted)]\">\n {tr(\n 'workspaces.form.creatingUnderOrg',\n 'Creating workspace under the selected organization.'\n )}\n </p>\n )}\n {errors.organizationId ? (\n <p className=\"mt-1 text-sm text-[var(--color-status-error-text)]\">\n {errors.organizationId}\n </p>\n ) : null}\n </div>\n </>\n ) : null}\n\n <div>\n <label\n htmlFor=\"name\"\n className=\"mb-1 block text-sm font-medium text-[var(--color-text-primary)]\"\n >\n {tr('workspaces.form.name', 'Workspace Name')}{' '}\n <span className=\"text-[var(--color-status-error-text)]\">*</span>\n </label>\n <input\n id=\"name\"\n type=\"text\"\n value={formData.name}\n aria-label={tr('workspaces.form.name', 'Workspace Name')}\n onChange={(event) =>\n setFormData((previousState) => ({ ...previousState, name: event.target.value }))\n }\n className=\"w-full rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] px-3 py-2 text-[var(--color-text-primary)] placeholder:text-[var(--color-text-muted)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]\"\n placeholder={tr('workspaces.form.namePlaceholder', 'Enter workspace name')}\n disabled={loading}\n required\n autoComplete=\"organization-title\"\n />\n {errors.name ? (\n <p className=\"mt-1 text-sm text-[var(--color-status-error-text)]\">{errors.name}</p>\n ) : null}\n </div>\n\n <div>\n <label\n htmlFor=\"slug\"\n className=\"mb-1 block text-sm font-medium text-[var(--color-text-primary)]\"\n >\n {tr('common.slug', 'Slug')}{' '}\n <span className=\"text-[var(--color-status-error-text)]\">*</span>\n </label>\n <input\n id=\"slug\"\n type=\"text\"\n value={formData.slug}\n aria-label={tr('common.slug', 'Slug')}\n onChange={(event) =>\n setFormData((previousState) => ({\n ...previousState,\n slug: event.target.value.toLowerCase().replace(/\\s+/g, '-'),\n }))\n }\n className=\"w-full rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] px-3 py-2 text-[var(--color-text-primary)] placeholder:text-[var(--color-text-muted)] focus:outline-none focus:ring-2 focus:ring-[var(--color-border-focus)] disabled:cursor-not-allowed disabled:bg-[var(--color-bg-muted)]\"\n placeholder={tr('workspaces.form.slugPlaceholder', 'workspace-slug')}\n disabled={loading || Boolean(workspace)}\n required={!workspace}\n autoComplete=\"off\"\n />\n <p className=\"mt-1 text-xs text-[var(--color-text-muted)]\">\n {tr(\n 'organizations.form.slugImmutable',\n 'Lowercase letters, numbers, and hyphens only. Cannot be changed after creation.'\n )}\n </p>\n {errors.slug ? (\n <p className=\"mt-1 text-sm text-[var(--color-status-error-text)]\">{errors.slug}</p>\n ) : null}\n </div>\n\n <div className=\"flex flex-col gap-3 border-t border-[var(--color-border-default)] pt-4 sm:flex-row\">\n <button\n type=\"submit\"\n disabled={loading}\n className=\"inline-flex items-center justify-center gap-2 rounded-lg bg-[var(--color-action-primary-bg)] px-6 py-2.5 font-medium text-[var(--color-action-primary-text)] transition-all duration-200 hover:opacity-90 hover:scale-[1.02] active:scale-[0.98] disabled:cursor-not-allowed disabled:opacity-50 sm:min-w-[220px]\"\n >\n {loading ? <Loader2 size={16} className=\"animate-spin\" /> : null}\n {workspace\n ? tr('workspaces.form.updateSubmit', 'Update Workspace')\n : tr('workspaces.create.button', 'Create Workspace')}\n </button>\n\n <button\n type=\"button\"\n onClick={onCancel}\n disabled={loading}\n className=\"rounded-lg border border-[var(--color-border-default)] bg-transparent px-6 py-2.5 font-medium text-[var(--color-text-primary)] transition-all duration-200 hover:bg-[var(--color-bg-subtle)] active:scale-[0.98] disabled:cursor-not-allowed disabled:opacity-50 sm:min-w-[140px]\"\n >\n {tr('common.cancel', 'Cancel')}\n </button>\n </div>\n </form>\n );\n}\n"],"mappings":"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"}